From 4d8f468f50e678da669ba8c7ac1f7a4d6ee09f95 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 4 Mar 2015 02:53:14 -0800 Subject: [PATCH 01/42] Fix DEPENDS markup --- DEPENDS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDS.txt b/DEPENDS.txt index 5cf37564..cec82e8c 100644 --- a/DEPENDS.txt +++ b/DEPENDS.txt @@ -49,7 +49,7 @@ functionality is only available with the following installed: Optional io plugin providing a wide variety of `formats `__. including specialized formats using in medical imaging. -* `imread ` +* `imread `__ Optional io plugin providing most standard `formats `__. From 11396fa285e89feda276f5eed81ae2cd4969de64 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 4 Mar 2015 02:55:53 -0800 Subject: [PATCH 02/42] Fix another formatting error in DEPENDS --- DEPENDS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDS.txt b/DEPENDS.txt index cec82e8c..c7f91df5 100644 --- a/DEPENDS.txt +++ b/DEPENDS.txt @@ -45,7 +45,7 @@ functionality is only available with the following installed: * `Astropy `__ provides FITS io capability. -* `SimpleITK ` +* `SimpleITK `__ Optional io plugin providing a wide variety of `formats `__. including specialized formats using in medical imaging. From 1da2446a1dc9beaa6379c93c7fce961dff67ad64 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 4 Mar 2015 18:41:26 -0800 Subject: [PATCH 03/42] Set master branch to 0.12 --- bento.info | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bento.info b/bento.info index 0af161d4..cba403d9 100644 --- a/bento.info +++ b/bento.info @@ -1,5 +1,5 @@ Name: scikit-image -Version: 0.11.0 +Version: 0.12.dev0 Summary: Image processing routines for SciPy Url: http://scikit-image.org DownloadUrl: http://github.com/scikit-image/scikit-image diff --git a/setup.py b/setup.py index 8ba529e5..0c76b698 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ MAINTAINER_EMAIL = 'stefan@sun.ac.za' URL = 'http://scikit-image.org' LICENSE = 'Modified BSD' DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image' -VERSION = '0.11.0' +VERSION = '0.12dev' PYTHON_VERSION = (2, 6) import os From 4efa68cd3052b43e7db2be74c128063966cbfdd0 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 4 Mar 2015 02:53:14 -0800 Subject: [PATCH 04/42] Fix DEPENDS markup --- DEPENDS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDS.txt b/DEPENDS.txt index 5cf37564..cec82e8c 100644 --- a/DEPENDS.txt +++ b/DEPENDS.txt @@ -49,7 +49,7 @@ functionality is only available with the following installed: Optional io plugin providing a wide variety of `formats `__. including specialized formats using in medical imaging. -* `imread ` +* `imread `__ Optional io plugin providing most standard `formats `__. From aa964efd599cf47c3345a2123b1686959f2ee87c Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 4 Mar 2015 02:55:53 -0800 Subject: [PATCH 05/42] Fix another formatting error in DEPENDS --- DEPENDS.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPENDS.txt b/DEPENDS.txt index cec82e8c..c7f91df5 100644 --- a/DEPENDS.txt +++ b/DEPENDS.txt @@ -45,7 +45,7 @@ functionality is only available with the following installed: * `Astropy `__ provides FITS io capability. -* `SimpleITK ` +* `SimpleITK `__ Optional io plugin providing a wide variety of `formats `__. including specialized formats using in medical imaging. From ac240eec58ac04db91bba3d1223b3ce9b91ef68e Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Thu, 5 Mar 2015 12:00:19 -0800 Subject: [PATCH 06/42] Update version to 0.11.2 --- bento.info | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bento.info b/bento.info index 0af161d4..fc67af8d 100644 --- a/bento.info +++ b/bento.info @@ -1,5 +1,5 @@ Name: scikit-image -Version: 0.11.0 +Version: 0.11.2 Summary: Image processing routines for SciPy Url: http://scikit-image.org DownloadUrl: http://github.com/scikit-image/scikit-image diff --git a/setup.py b/setup.py index 8ba529e5..7cda1026 100755 --- a/setup.py +++ b/setup.py @@ -17,7 +17,7 @@ MAINTAINER_EMAIL = 'stefan@sun.ac.za' URL = 'http://scikit-image.org' LICENSE = 'Modified BSD' DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image' -VERSION = '0.11.0' +VERSION = '0.11.2' PYTHON_VERSION = (2, 6) import os From 10af2b21ee1992b3a1009e7f13aa426ab59ff15b Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 5 Mar 2015 16:17:57 -0800 Subject: [PATCH 07/42] Use relative imports to plugins. Otherwise e.g. skivi fails to start. --- skimage/io/_plugins/gtk_plugin.py | 2 +- skimage/io/_plugins/q_color_mixer.py | 2 +- skimage/io/_plugins/q_histogram.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/io/_plugins/gtk_plugin.py b/skimage/io/_plugins/gtk_plugin.py index 6130289c..327d762d 100644 --- a/skimage/io/_plugins/gtk_plugin.py +++ b/skimage/io/_plugins/gtk_plugin.py @@ -1,4 +1,4 @@ -from util import prepare_for_display, window_manager, GuiLockError +from .util import prepare_for_display, window_manager, GuiLockError try: # we try to aquire the gui lock first diff --git a/skimage/io/_plugins/q_color_mixer.py b/skimage/io/_plugins/q_color_mixer.py index 3fe9e29c..87402a37 100644 --- a/skimage/io/_plugins/q_color_mixer.py +++ b/skimage/io/_plugins/q_color_mixer.py @@ -2,7 +2,7 @@ from PyQt4 import QtGui, QtCore from PyQt4.QtGui import (QWidget, QStackedWidget, QSlider, QGridLayout, QLabel) -from util import ColorMixer +from .util import ColorMixer class IntelligentSlider(QWidget): diff --git a/skimage/io/_plugins/q_histogram.py b/skimage/io/_plugins/q_histogram.py index 0a60ce9f..4b1b545b 100644 --- a/skimage/io/_plugins/q_histogram.py +++ b/skimage/io/_plugins/q_histogram.py @@ -2,7 +2,7 @@ import numpy as np from PyQt4.QtGui import QWidget, QPainter, QGridLayout, QColor, QFrame -from util import histograms +from .util import histograms class ColorHistogram(QWidget): From b2030394621203c5950dab34e99a7235c05fb8cf Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Fri, 6 Mar 2015 01:21:05 -0800 Subject: [PATCH 08/42] Update tagging instructions for release --- RELEASE.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index 66860662..02602017 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -31,7 +31,10 @@ How to make a new release of ``skimage`` - Add the version number as a tag in git:: - git tag v0.X.0 + git tag -s v0.X.0 + + (If you do not have a gpg key, use -m instead; it is important for + Debian packaging that the tags are annotated) - Push the new meta-data to github:: From eb6c3ede3824da2b44fa3bafda81844366c813ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Fri, 6 Mar 2015 23:47:08 -0500 Subject: [PATCH 09/42] Fix RANSAC for invalid model estimation and confidence corner case Previously, estimators did not return whether the model estimation was successful. RANSAC now tests whether the estimation was successful and skips invalid models. When the confidence/stop_probability of RANSAC was set to 1, the iteration was falsely terminated early instead of running for the maximum number of iterations. --- skimage/measure/fit.py | 64 +++++++++++++++++++++++-------- skimage/measure/tests/test_fit.py | 6 +-- skimage/transform/_geometric.py | 31 ++++++++++++++- 3 files changed, 81 insertions(+), 20 deletions(-) diff --git a/skimage/measure/fit.py b/skimage/measure/fit.py index 7de90291..c47a5c6f 100644 --- a/skimage/measure/fit.py +++ b/skimage/measure/fit.py @@ -4,9 +4,6 @@ import numpy as np from scipy import optimize -_EPSILON = np.spacing(1) - - def _check_data_dim(data, dim): if data.ndim != 2 or data.shape[1] != dim: raise ValueError('Input data must have shape (N, %d).' % dim) @@ -57,6 +54,11 @@ class LineModel(BaseModel): data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ _check_data_dim(data, dim=2) @@ -81,6 +83,8 @@ class LineModel(BaseModel): self.params = (dist, theta) + return True + def residuals(self, data): """Determine residuals of data to model. @@ -182,6 +186,11 @@ class CircleModel(BaseModel): data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ _check_data_dim(data, dim=2) @@ -217,6 +226,8 @@ class CircleModel(BaseModel): self.params = params + return True + def residuals(self, data): """Determine residuals of data to model. @@ -313,6 +324,11 @@ class EllipseModel(BaseModel): data : (N, 2) array N points with ``(x, y)`` coordinates, respectively. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ _check_data_dim(data, dim=2) @@ -373,6 +389,8 @@ class EllipseModel(BaseModel): self.params = params[:5] + return True + def residuals(self, data): """Determine residuals of data to model. @@ -471,7 +489,6 @@ class EllipseModel(BaseModel): def _dynamic_max_trials(n_inliers, n_samples, min_samples, probability): """Determine number trials such that at least one outlier-free subset is sampled for the given inlier/outlier ratio. - Parameters ---------- n_inliers : int @@ -482,21 +499,31 @@ def _dynamic_max_trials(n_inliers, n_samples, min_samples, probability): Minimum number of samples chosen randomly from original data. probability : float Probability (confidence) that one outlier-free sample is generated. - Returns ------- trials : int Number of trials. - """ - inlier_ratio = n_inliers / float(n_samples) - nom = max(_EPSILON, 1 - probability) - denom = max(_EPSILON, 1 - inlier_ratio ** min_samples) - if nom == 1: - return 0 - if denom == 1: + if n_inliers == 0: return float('inf') - return abs(float(np.ceil(np.log(nom) / np.log(denom)))) + + nom = 1 - probability + if nom == 0: + return float('inf') + + inlier_ratio = n_inliers / float(n_samples) + denom = 1 - inlier_ratio ** min_samples + if denom == 0: + return 1 + elif denom == 1: + return float('inf') + + nom = np.log(nom) + denom = np.log(denom) + if denom == 0: + return 0 + + return int(np.ceil(nom / denom)) def ransac(data, model_class, min_samples, residual_threshold, @@ -542,9 +569,11 @@ def ransac(data, model_class, min_samples, residual_threshold, model_class : object Object with the following object methods: - * ``estimate(*data)`` + * ``success = estimate(*data)`` * ``residuals(*data)`` + where `success` indicates whether the model estimation succeeded + (`True` or `None` for success, `False` for failure). min_samples : int The minimum number of data points to fit a model to. residual_threshold : float @@ -688,7 +717,12 @@ def ransac(data, model_class, min_samples, residual_threshold, # estimate model for current random sample set sample_model = model_class() - sample_model.estimate(*samples) + + success = sample_model.estimate(*samples) + + if success is not None: # backwards compatibility + if not success: + continue # check if estimated model is valid if is_model_valid is not None and not is_model_valid(sample_model, diff --git a/skimage/measure/tests/test_fit.py b/skimage/measure/tests/test_fit.py index 1b960d4b..1c3a6f43 100644 --- a/skimage/measure/tests/test_fit.py +++ b/skimage/measure/tests/test_fit.py @@ -233,9 +233,9 @@ def test_ransac_dynamic_max_trials(): # e = 50%, min_samples = 8 assert_equal(_dynamic_max_trials(50, 100, 8, 0.99), 1177) - # e = 0%, min_samples = 10 - assert_equal(_dynamic_max_trials(1, 100, 10, 0), 0) - assert_equal(_dynamic_max_trials(1, 100, 10, 1), float('inf')) + # e = 0%, min_samples = 5 + assert_equal(_dynamic_max_trials(1, 100, 5, 0), 0) + assert_equal(_dynamic_max_trials(1, 100, 5, 1), float('inf')) def test_ransac_invalid_input(): diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index c94e3b76..33448353 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -263,6 +263,11 @@ class ProjectiveTransform(GeometricTransform): dst : (N, 2) array Destination coordinates. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ try: @@ -270,7 +275,7 @@ class ProjectiveTransform(GeometricTransform): dst_matrix, dst = _center_and_normalize_points(dst) except ZeroDivisionError: self.params = np.nan * np.empty((3, 3)) - return + return False xs = src[:, 0] ys = src[:, 1] @@ -309,6 +314,8 @@ class ProjectiveTransform(GeometricTransform): self.params = H + return True + def __add__(self, other): """Combine this transformation with another. @@ -459,6 +466,11 @@ class PiecewiseAffineTransform(GeometricTransform): dst : (N, 2) array Destination coordinates. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ # forward piecewise affine @@ -481,6 +493,8 @@ class PiecewiseAffineTransform(GeometricTransform): affine.estimate(dst[tri, :], src[tri, :]) self.inverse_affines.append(affine) + return True + def __call__(self, coords): """Apply forward transformation. @@ -658,6 +672,11 @@ class SimilarityTransform(ProjectiveTransform): dst : (N, 2) array Destination coordinates. + Returns + ------- + success : bool + True, if model estimation succeeds. + """ try: @@ -665,7 +684,7 @@ class SimilarityTransform(ProjectiveTransform): dst_matrix, dst = _center_and_normalize_points(dst) except ZeroDivisionError: self.params = np.nan * np.empty((3, 3)) - return + return False xs = src[:, 0] ys = src[:, 1] @@ -699,6 +718,7 @@ class SimilarityTransform(ProjectiveTransform): self.params = S + return True @property def scale(self): @@ -798,6 +818,11 @@ class PolynomialTransform(GeometricTransform): order : int, optional Polynomial order (number of coefficients is order + 1). + Returns + ------- + success : bool + True, if model estimation succeeds. + """ xs = src[:, 0] ys = src[:, 1] @@ -828,6 +853,8 @@ class PolynomialTransform(GeometricTransform): self.params = params.reshape((2, u // 2)) + return True + def __call__(self, coords): """Apply forward transformation. From d6a737bf8618165a2544517e68682ade11163fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Sun, 8 Mar 2015 13:13:46 -0400 Subject: [PATCH 10/42] Update doctest for new estimator API --- skimage/measure/fit.py | 1 + 1 file changed, 1 insertion(+) diff --git a/skimage/measure/fit.py b/skimage/measure/fit.py index c47a5c6f..ad48101b 100644 --- a/skimage/measure/fit.py +++ b/skimage/measure/fit.py @@ -641,6 +641,7 @@ def ransac(data, model_class, min_samples, residual_threshold, >>> model = EllipseModel() >>> model.estimate(data) + True >>> model.params # doctest: +SKIP array([ -3.30354146e+03, -2.87791160e+03, 5.59062118e+03, 7.84365066e+00, 7.19203152e-01]) From 47a4418140d10fba79793341033c3d58535cbc8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Sun, 8 Mar 2015 19:37:53 -0400 Subject: [PATCH 11/42] Use np.inf instead of float('inf') --- skimage/measure/fit.py | 6 +++--- skimage/measure/tests/test_fit.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/skimage/measure/fit.py b/skimage/measure/fit.py index ad48101b..f8e65117 100644 --- a/skimage/measure/fit.py +++ b/skimage/measure/fit.py @@ -505,18 +505,18 @@ def _dynamic_max_trials(n_inliers, n_samples, min_samples, probability): Number of trials. """ if n_inliers == 0: - return float('inf') + return np.inf nom = 1 - probability if nom == 0: - return float('inf') + return np.inf inlier_ratio = n_inliers / float(n_samples) denom = 1 - inlier_ratio ** min_samples if denom == 0: return 1 elif denom == 1: - return float('inf') + return np.inf nom = np.log(nom) denom = np.log(denom) diff --git a/skimage/measure/tests/test_fit.py b/skimage/measure/tests/test_fit.py index 1c3a6f43..7f98c971 100644 --- a/skimage/measure/tests/test_fit.py +++ b/skimage/measure/tests/test_fit.py @@ -235,7 +235,7 @@ def test_ransac_dynamic_max_trials(): # e = 0%, min_samples = 5 assert_equal(_dynamic_max_trials(1, 100, 5, 0), 0) - assert_equal(_dynamic_max_trials(1, 100, 5, 1), float('inf')) + assert_equal(_dynamic_max_trials(1, 100, 5, 1), np.inf) def test_ransac_invalid_input(): From 0e61374a899ab776e2652622759bfb741f4872b3 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 7 Mar 2015 09:29:04 -0600 Subject: [PATCH 12/42] Add a helper function to check for low contrast Add a helper function to check for low contrast Add a check for low contrast when using imsave Use the low contrast helper in imshow and make sure warnings are always shown Clean up parameter names and add doctests Remove unnecessary warning context Remove unnecessary warning context Add dtype ranges for 64bit types Update tests with new warnings Fix doctest logic Fix doctest logic Add a low contrast test with multiple dtypes Fix check for color images Fix color check again Add support for int32 types Relax assertion for 32bit builds Add a low contrast test with multiple dtypes Add a low contrast test with multiple dtypes Fix check for color images Fix color check again Add support for int32 types --- skimage/exposure/__init__.py | 6 ++- skimage/exposure/exposure.py | 48 ++++++++++++++++++++++- skimage/exposure/tests/test_exposure.py | 16 ++++++++ skimage/io/_io.py | 5 +++ skimage/io/_plugins/matplotlib_plugin.py | 10 +++-- skimage/io/tests/test_mpl_imshow.py | 3 +- skimage/io/tests/test_pil.py | 3 +- skimage/measure/tests/test_regionprops.py | 2 +- skimage/util/dtype.py | 4 ++ 9 files changed, 87 insertions(+), 10 deletions(-) diff --git a/skimage/exposure/__init__.py b/skimage/exposure/__init__.py index d78cf927..1950f37a 100644 --- a/skimage/exposure/__init__.py +++ b/skimage/exposure/__init__.py @@ -1,6 +1,7 @@ from .exposure import histogram, equalize_hist, \ rescale_intensity, cumulative_distribution, \ - adjust_gamma, adjust_sigmoid, adjust_log + adjust_gamma, adjust_sigmoid, adjust_log, \ + is_low_contrast from ._adapthist import equalize_adapthist @@ -12,4 +13,5 @@ __all__ = ['histogram', 'cumulative_distribution', 'adjust_gamma', 'adjust_sigmoid', - 'adjust_log'] + 'adjust_log', + 'is_low_contrast'] diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py index 8774cf9b..dc2faebd 100644 --- a/skimage/exposure/exposure.py +++ b/skimage/exposure/exposure.py @@ -1,7 +1,8 @@ +from __future__ import division import warnings import numpy as np -from .. import img_as_float +from ..color import rgb2gray from ..util.dtype import dtype_range, dtype_limits @@ -463,3 +464,48 @@ def adjust_sigmoid(image, cutoff=0.5, gain=10, inv=False): out = (1 / (1 + np.exp(gain * (cutoff - image / scale)))) * scale return dtype(out) + + +def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1, + upper_percentile=99, method='linear'): + """Detemine if an image is low contrast. + + Parameters + ---------- + image : array-like + The image under test. + fraction_threshold : float, optional + The low contrast fraction threshold. + lower_bound : float, optional + Disregard values below this percentile when computing image contrast. + upper_bound : float, optional + Disregard values above this percentile when computing image contrast. + method : str, optional + The contrast determination method. Right now the only available + option is "linear". + + Returns + ------- + out : bool + True when the image is determined to be low contrast. + + Examples + -------- + >>> image = np.linspace(0, 0.04, 100) + >>> is_low_contrast(image) + True + >>> image[-1] = 1 + >>> is_low_contrast(image) + True + >>> is_low_contrast(image, upper_percentile=100) + False + """ + image = np.asanyarray(image) + if image.ndim == 3 and image.shape[2] in [3, 4]: + image = rgb2gray(image) + + dlimits = dtype_limits(image) + limits = np.percentile(image, [lower_percentile, upper_percentile]) + ratio = (limits[1] - limits[0]) / (dlimits[1] - dlimits[0]) + + return ratio < fraction_threshold diff --git a/skimage/exposure/tests/test_exposure.py b/skimage/exposure/tests/test_exposure.py index 1316ea4e..265ce246 100644 --- a/skimage/exposure/tests/test_exposure.py +++ b/skimage/exposure/tests/test_exposure.py @@ -472,6 +472,22 @@ def test_negative(): assert_raises(ValueError, exposure.adjust_gamma, image) +def test_is_low_contrast(): + image = np.linspace(0, 0.04, 100) + assert exposure.is_low_contrast(image) + image[-1] = 1 + assert exposure.is_low_contrast(image) + assert not exposure.is_low_contrast(image, upper_percentile=100) + + image = (image * 255).astype(np.uint8) + assert exposure.is_low_contrast(image) + assert not exposure.is_low_contrast(image, upper_percentile=100) + + image = (image.astype(np.uint16)) * 2**8 + assert exposure.is_low_contrast(image) + assert not exposure.is_low_contrast(image, upper_percentile=100) + + if __name__ == '__main__': from numpy import testing testing.run_module_suite() diff --git a/skimage/io/_io.py b/skimage/io/_io.py index f44bfd8b..e76c36f6 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -1,4 +1,5 @@ from io import BytesIO +import warnings import numpy as np import six @@ -6,6 +7,8 @@ import six from ..io.manage_plugins import call_plugin from ..color import rgb2grey from .util import file_or_url_context +from ..exposure import is_low_contrast +from .._shared._warnings import all_warnings __all__ = ['Image', 'imread', 'imread_collection', 'imsave', 'imshow', 'show'] @@ -152,6 +155,8 @@ def imsave(fname, arr, plugin=None, **plugin_args): Passed to the given plugin. """ + if is_low_contrast(arr): + warnings.warn('%s is a low contrast image' % fname) return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args) diff --git a/skimage/io/_plugins/matplotlib_plugin.py b/skimage/io/_plugins/matplotlib_plugin.py index 2de61ecf..32ebf2fd 100644 --- a/skimage/io/_plugins/matplotlib_plugin.py +++ b/skimage/io/_plugins/matplotlib_plugin.py @@ -2,7 +2,9 @@ from collections import namedtuple import numpy as np import warnings import matplotlib.pyplot as plt -from skimage.util import dtype as dtypes +from ...util import dtype as dtypes +from ...exposure import is_low_contrast +from ..._shared._warnings import all_warnings _default_colormap = 'gray' @@ -49,7 +51,7 @@ def _get_image_properties(image): out_of_range_float = (np.issubdtype(image.dtype, np.float) and (immin < lo or immax > hi)) low_dynamic_range = (immin != immax and - (float(immax - immin) / (hi - lo)) < (1. / 255)) + is_low_contrast(image)) unsupported_dtype = image.dtype not in dtypes._supported_types return ImageProperties(signed, out_of_range_float, @@ -72,8 +74,8 @@ def _raise_warnings(image_properties): warnings.warn("Low image dynamic range; displaying image with " "stretched contrast.") if ip.out_of_range_float: - warnings.warn("Float image out of standard range; displaying image " - "with stretched contrast.") + warnings.warn("Float image out of standard range; displaying " + "image with stretched contrast.") def _get_display_range(image): diff --git a/skimage/io/tests/test_mpl_imshow.py b/skimage/io/tests/test_mpl_imshow.py index aad51048..166c8cbc 100644 --- a/skimage/io/tests/test_mpl_imshow.py +++ b/skimage/io/tests/test_mpl_imshow.py @@ -87,7 +87,8 @@ def test_outside_standard_range(): def test_nonstandard_type(): plt.figure() - with expected_warnings(["Non-standard image type"]): + with expected_warnings(["Non-standard image type", + "Low image dynamic range"]): ax_im = io.imshow(im64) assert ax_im.get_clim() == (im64.min(), im64.max()) assert n_subplots(ax_im) == 2 diff --git a/skimage/io/tests/test_pil.py b/skimage/io/tests/test_pil.py index fc28ce89..e8909503 100644 --- a/skimage/io/tests/test_pil.py +++ b/skimage/io/tests/test_pil.py @@ -147,7 +147,8 @@ def test_imsave_filelike(): s = BytesIO() # save to file-like object - with expected_warnings(['precision loss|unclosed file']): + with expected_warnings(['precision loss|unclosed file', + 'is a low contrast image']): imsave(s, image) # read from file-like object diff --git a/skimage/measure/tests/test_regionprops.py b/skimage/measure/tests/test_regionprops.py index 3ac735c7..487d782e 100644 --- a/skimage/measure/tests/test_regionprops.py +++ b/skimage/measure/tests/test_regionprops.py @@ -26,7 +26,7 @@ INTENSITY_SAMPLE[1, 9:11] = 2 def test_all_props(): region = regionprops(SAMPLE, INTENSITY_SAMPLE)[0] for prop in PROPS: - assert_equal(region[prop], getattr(region, PROPS[prop])) + assert_almost_equal(region[prop], getattr(region, PROPS[prop])) def test_dtype(): diff --git a/skimage/util/dtype.py b/skimage/util/dtype.py index 0e7bc060..1c594534 100644 --- a/skimage/util/dtype.py +++ b/skimage/util/dtype.py @@ -11,6 +11,10 @@ dtype_range = {np.bool_: (False, True), np.uint16: (0, 65535), np.int8: (-128, 127), np.int16: (-32768, 32767), + np.int64: (-2**63, 2**63 - 1), + np.uint64: (0, 2**64 - 1), + np.int32: (-2**31, 2**31 - 1), + np.uint32: (0, 2**32 - 1), np.float32: (-1, 1), np.float64: (-1, 1)} From c62397493ac9c457527dfb4f39df6162f3a0e34b Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 13 Mar 2015 08:18:50 -0500 Subject: [PATCH 13/42] Handle Sphinx 1.3 API change --- doc/ext/plot2rst.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/ext/plot2rst.py b/doc/ext/plot2rst.py index 99fd9a3f..1a35a8a2 100644 --- a/doc/ext/plot2rst.py +++ b/doc/ext/plot2rst.py @@ -205,6 +205,9 @@ def generate_examples_and_gallery(example_dir, rst_dir, cfg): rst_dir.makedirs() # we create an index.rst with all examples + if isinstance(cfg.source_suffix, list): + cfg.source_suffix = cfg.source_suffix[0] + gallery_index = open(rst_dir.pjoin('index'+cfg.source_suffix), 'w') # Here we don't use an os.walk, but we recurse only twice: flat is From 7d65366b6737a8812ea1c156b8793de5024ede9f Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 13 Mar 2015 22:07:04 -0500 Subject: [PATCH 14/42] Try a fix for py27 build --- Makefile | 2 +- tools/travis_script.sh | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b80eba0d..2de60516 100644 --- a/Makefile +++ b/Makefile @@ -16,5 +16,5 @@ coverage: nosetests skimage --with-coverage --cover-package=skimage html: - pip install -q sphinx + pip install -q sphinx==1.2.3 export SPHINXOPTS=-W; make -C doc html diff --git a/tools/travis_script.sh b/tools/travis_script.sh index 8dc2bb4e..3ffb58f1 100755 --- a/tools/travis_script.sh +++ b/tools/travis_script.sh @@ -10,6 +10,7 @@ section_end "Test.with.min.requirements" section "Build.docs" if [[ ($PY != 2.6) && ($PY != 3.2) ]]; then sudo apt-get install -qq texlive texlive-latex-extra dvipng + pip install -U setuptools pip make html fi section_end "Build.docs" From 9c3a6c1e9140dfd4e334ae4c4e8104604eb60073 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Mar 2015 10:35:04 -0500 Subject: [PATCH 15/42] Fix support for Sphinx 1.3 --- doc/ext/plot2rst.py | 15 +++++++++------ doc/source/conf.py | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/doc/ext/plot2rst.py b/doc/ext/plot2rst.py index 1a35a8a2..32811deb 100644 --- a/doc/ext/plot2rst.py +++ b/doc/ext/plot2rst.py @@ -186,6 +186,11 @@ def setup(app): def generate_example_galleries(app): cfg = app.builder.config + if isinstance(cfg.source_suffix, list): + cfg.source_suffix_str = cfg.source_suffix[0] + else: + cfg.source_suffix_str = cfg.source_suffix + doc_src = Path(os.path.abspath(app.builder.srcdir)) # path/to/doc/source if isinstance(cfg.plot2rst_paths, tuple): @@ -205,10 +210,7 @@ def generate_examples_and_gallery(example_dir, rst_dir, cfg): rst_dir.makedirs() # we create an index.rst with all examples - if isinstance(cfg.source_suffix, list): - cfg.source_suffix = cfg.source_suffix[0] - - gallery_index = open(rst_dir.pjoin('index'+cfg.source_suffix), 'w') + gallery_index = open(rst_dir.pjoin('index'+cfg.source_suffix_str), 'w') # Here we don't use an os.walk, but we recurse only twice: flat is # better than nested. @@ -238,7 +240,7 @@ def write_gallery(gallery_index, src_dir, rst_dir, cfg, depth=0): cfg : config object Sphinx config object created by Sphinx. """ - index_name = cfg.plot2rst_index_name + cfg.source_suffix + index_name = cfg.plot2rst_index_name + cfg.source_suffix_str gallery_template = src_dir.pjoin(index_name) if not os.path.exists(gallery_template): print(src_dir) @@ -331,7 +333,8 @@ def write_example(src_name, src_dir, rst_dir, cfg): image_path = image_dir.pjoin(base_image_name + '_{0}.png') basename, py_ext = os.path.splitext(src_name) - rst_path = rst_dir.pjoin(basename + cfg.source_suffix) + + rst_path = rst_dir.pjoin(basename + cfg.source_suffix_str) notebook_path = notebook_dir.pjoin(basename + '.ipynb') if _plots_are_current(src_path, image_path) and rst_path.exists and \ diff --git a/doc/source/conf.py b/doc/source/conf.py index 94904305..be2d0790 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,6 +12,7 @@ # serve to show the default. import sys, os +import sphinx # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -50,7 +51,10 @@ else: templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.txt' +if sphinx.__version__.startswith('1.3'): + source_suffix = ['.txt'] +else: + source_suffix = '.txt' # The encoding of source files. #source_encoding = 'utf-8-sig' From 15f6497bfecd26027f33e73cee07ff88e90869d0 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Mar 2015 10:35:59 -0500 Subject: [PATCH 16/42] Revert changes to force Sphinx 1.2.3 --- Makefile | 2 +- tools/travis_script.sh | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2de60516..b80eba0d 100644 --- a/Makefile +++ b/Makefile @@ -16,5 +16,5 @@ coverage: nosetests skimage --with-coverage --cover-package=skimage html: - pip install -q sphinx==1.2.3 + pip install -q sphinx export SPHINXOPTS=-W; make -C doc html diff --git a/tools/travis_script.sh b/tools/travis_script.sh index 3ffb58f1..8dc2bb4e 100755 --- a/tools/travis_script.sh +++ b/tools/travis_script.sh @@ -10,7 +10,6 @@ section_end "Test.with.min.requirements" section "Build.docs" if [[ ($PY != 2.6) && ($PY != 3.2) ]]; then sudo apt-get install -qq texlive texlive-latex-extra dvipng - pip install -U setuptools pip make html fi section_end "Build.docs" From 5c6ee9511ce40a37b3b46da6fc20b2a99be4e199 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 14 Mar 2015 10:39:25 -0500 Subject: [PATCH 17/42] Remove unnecessary sphinx version check --- doc/source/conf.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index be2d0790..94904305 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -12,7 +12,6 @@ # serve to show the default. import sys, os -import sphinx # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -51,10 +50,7 @@ else: templates_path = ['_templates'] # The suffix of source filenames. -if sphinx.__version__.startswith('1.3'): - source_suffix = ['.txt'] -else: - source_suffix = '.txt' +source_suffix = '.txt' # The encoding of source files. #source_encoding = 'utf-8-sig' From f737ac4496d79692105f772b834883dc8213a70a Mon Sep 17 00:00:00 2001 From: arve0 Date: Mon, 23 Feb 2015 15:50:12 +0100 Subject: [PATCH 18/42] move docstring from viewer.widgets.core to viewer.widgets --- skimage/viewer/widgets/__init__.py | 18 ++++++++++++++++++ skimage/viewer/widgets/core.py | 19 +------------------ 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/skimage/viewer/widgets/__init__.py b/skimage/viewer/widgets/__init__.py index efa9fe9d..2705f371 100644 --- a/skimage/viewer/widgets/__init__.py +++ b/skimage/viewer/widgets/__init__.py @@ -1,2 +1,20 @@ +""" +Widgets for interacting with ImageViewer. + +These widgets should be added to a Plugin subclass using its `add_widget` +method or calling:: + + plugin += Widget(...) + +on a Plugin instance. The Plugin will delegate action based on the widget's +parameter type specified by its `ptype` attribute, which can be:: + + 'arg' : positional argument passed to Plugin's `filter_image` method. + 'kwarg' : keyword argument passed to Plugin's `filter_image` method. + 'plugin' : attribute of Plugin. You'll probably need to add a class + property of the same name that updates the display. + +""" + from .core import * from .history import * diff --git a/skimage/viewer/widgets/core.py b/skimage/viewer/widgets/core.py index ae8be4e7..71f0bc50 100644 --- a/skimage/viewer/widgets/core.py +++ b/skimage/viewer/widgets/core.py @@ -1,20 +1,3 @@ -""" -Widgets for interacting with ImageViewer. - -These widgets should be added to a Plugin subclass using its `add_widget` -method or calling:: - - plugin += Widget(...) - -on a Plugin instance. The Plugin will delegate action based on the widget's -parameter type specified by its `ptype` attribute, which can be: - - 'arg' : positional argument passed to Plugin's `filter_image` method. - 'kwarg' : keyword argument passed to Plugin's `filter_image` method. - 'plugin' : attribute of Plugin. You'll probably need to add a class - property of the same name that updates the display. - -""" from ..qt import QtWidgets, QtCore, Qt from ..utils import RequiredAttr @@ -275,7 +258,7 @@ class CheckBox(BaseWidget): added to a plugin. """ - def __init__(self, name, value=False, alignment='center', ptype='kwarg', + def __init__(self, name, value=False, alignment='center', ptype='kwarg', callback=None): super(CheckBox, self).__init__(name, ptype, callback) From ae95170f6a1a0b302d67fef22e0a72043a0d8f25 Mon Sep 17 00:00:00 2001 From: arve0 Date: Sat, 14 Mar 2015 12:17:36 +0100 Subject: [PATCH 19/42] add note about latex --- doc/README.md | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/doc/README.md b/doc/README.md index 50deb4e2..c89500e7 100644 --- a/doc/README.md +++ b/doc/README.md @@ -2,13 +2,31 @@ To build docs, run `make` in this directory. `make help` lists all targets. ## Requirements ## -Sphinx is needed to build doc. Install with `pip install sphinx`. +Sphinx and Latex is needed to build doc. + +**Spinx:** +```sh +pip install sphinx +``` + +**Latex Ubuntu:** +```sh +sudo apt-get install -qq texlive texlive-latex-extra dvipng +``` + +**Latex Mac:** + +Install the full [MacTex](http://www.tug.org/mactex/) installation or install the smaller [BasicTex](http://www.tug.org/mactex/morepackages.html) and add *ucs* and *dvipng* packages: +```sh +sudo tlmgr install ucs dvipng +``` + ## Fixing Warnings ## - "citation not found: R###" $ cd doc/build; grep -rin R### . - There is probably an underscore after a reference + There is probably an underscore after a reference in the first line of a docstring (e.g. [1]_) - "Duplicate citation R###, other instance in..."" From d745e9c46e0d2f87b45c3aaa27dad6786b545cc7 Mon Sep 17 00:00:00 2001 From: "Josh Warner (Mac)" Date: Sat, 14 Mar 2015 16:15:31 -0500 Subject: [PATCH 20/42] DOC: Fix Sphinx rendering of dev process docs --- CONTRIBUTING.txt | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/CONTRIBUTING.txt b/CONTRIBUTING.txt index 58b83296..0fa66ddd 100644 --- a/CONTRIBUTING.txt +++ b/CONTRIBUTING.txt @@ -19,8 +19,8 @@ Here's the long and short of it: * Now, you have remote repositories named: - - ``upstream``, which refers to the ``scikit-image`` repository - - ``origin``, which refers to your personal fork + - ``upstream``, which refers to the ``scikit-image`` repository + - ``origin``, which refers to your personal fork 2. Develop your contribution: @@ -56,32 +56,32 @@ For a more detailed discussion, read these :doc:`detailed documents 4. Review process: - * Reviewers (the other developers and interested community members) will - write inline and/or general comments on your Pull Request (PR) to help - you improve its implementation, documentation and style. Every single - developer working on the project has their code reviewed, and we've come - to see it as friendly conversation from which we all learn and the - overall code quality benefits. Therefore, please don't let the review - discourage you from contributing: its only aim is to improve the quality - of project, not to criticize (we are, after all, very grateful for the - time you're donating!). + * Reviewers (the other developers and interested community members) will + write inline and/or general comments on your Pull Request (PR) to help + you improve its implementation, documentation and style. Every single + developer working on the project has their code reviewed, and we've come + to see it as friendly conversation from which we all learn and the + overall code quality benefits. Therefore, please don't let the review + discourage you from contributing: its only aim is to improve the quality + of project, not to criticize (we are, after all, very grateful for the + time you're donating!). - * To update your pull request, make your changes on your local repository - and commit. As soon as those changes are pushed up (to the same branch as - before) the pull request will update automatically. + * To update your pull request, make your changes on your local repository + and commit. As soon as those changes are pushed up (to the same branch as + before) the pull request will update automatically. - * `Travis-CI `__, a continuous integration service, - is triggered after each Pull Request update to build the code, run unit - tests, measure code coverage and check coding style (PEP8) of your - branch. The Travis tests must pass before your PR can be merged. If - Travis fails, you can find out why by clicking on the "failed" icon (red - cross) and inspecting the build and test log. + * `Travis-CI `__, a continuous integration service, + is triggered after each Pull Request update to build the code, run unit + tests, measure code coverage and check coding style (PEP8) of your + branch. The Travis tests must pass before your PR can be merged. If + Travis fails, you can find out why by clicking on the "failed" icon (red + cross) and inspecting the build and test log. 5. Document changes - Before merging your commits, you must add a description of your changes - to the release notes of the upcoming version in - ``doc/release/release_dev.txt``. + Before merging your commits, you must add a description of your changes + to the release notes of the upcoming version in + ``doc/release/release_dev.txt``. .. note:: @@ -191,10 +191,11 @@ Travis-CI checks all unittests in the project to prevent breakage. Before sending a pull request, you may want to check that Travis-CI successfully passes all tests. To do so, - * Go to `Travis-CI `__ and follow the Sign In link at the top +* Go to `Travis-CI `__ and follow the Sign In link at + the top - * Go to your `profile page `__ and switch - on your scikit-image fork +* Go to your `profile page `__ and switch on + your scikit-image fork It corresponds to steps one and two in `Travis-CI documentation `__ From 6fceaa2f7544897ed7907ce8059b496eda69fd36 Mon Sep 17 00:00:00 2001 From: arve0 Date: Sat, 14 Mar 2015 23:22:15 +0100 Subject: [PATCH 21/42] import from _label instead of _ccomp --- skimage/measure/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/measure/__init__.py b/skimage/measure/__init__.py index e2a4a51a..9731d6da 100755 --- a/skimage/measure/__init__.py +++ b/skimage/measure/__init__.py @@ -9,7 +9,7 @@ from ._moments import moments, moments_central, moments_normalized, moments_hu from .profile import profile_line from .fit import LineModel, CircleModel, EllipseModel, ransac from .block import block_reduce -from ._ccomp import label +from ._label import label __all__ = ['find_contours', From 2f62cf9d2e9ad06f9139e8cbf66a1256f964bdab Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Wed, 11 Mar 2015 00:41:50 +1100 Subject: [PATCH 22/42] Clarify 'low-contrast' in docstring --- skimage/exposure/exposure.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py index dc2faebd..a0787294 100644 --- a/skimage/exposure/exposure.py +++ b/skimage/exposure/exposure.py @@ -475,7 +475,9 @@ def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1, image : array-like The image under test. fraction_threshold : float, optional - The low contrast fraction threshold. + The low contrast fraction threshold. An image is considered low- + contrast when its range of brightness spans less than this + fraction of its data type's full range. [1]_ lower_bound : float, optional Disregard values below this percentile when computing image contrast. upper_bound : float, optional @@ -499,6 +501,10 @@ def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1, True >>> is_low_contrast(image, upper_percentile=100) False + + See Also + -------- + .. [1] http://scikit-image.org/docs/dev/user_guide/data_types.html """ image = np.asanyarray(image) if image.ndim == 3 and image.shape[2] in [3, 4]: From 0d3d5f13198bad704d763bdf07b09f6f8aa11419 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Wed, 11 Mar 2015 09:33:17 +1100 Subject: [PATCH 23/42] Update See Also to References "See Also" is apparently reserved by sphinx-numpydoc for pointers to other code functions, rather than documentation. --- skimage/exposure/exposure.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/skimage/exposure/exposure.py b/skimage/exposure/exposure.py index a0787294..0cad7bbe 100644 --- a/skimage/exposure/exposure.py +++ b/skimage/exposure/exposure.py @@ -491,6 +491,10 @@ def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1, out : bool True when the image is determined to be low contrast. + References + ---------- + .. [1] http://scikit-image.org/docs/dev/user_guide/data_types.html + Examples -------- >>> image = np.linspace(0, 0.04, 100) @@ -501,10 +505,6 @@ def is_low_contrast(image, fraction_threshold=0.05, lower_percentile=1, True >>> is_low_contrast(image, upper_percentile=100) False - - See Also - -------- - .. [1] http://scikit-image.org/docs/dev/user_guide/data_types.html """ image = np.asanyarray(image) if image.ndim == 3 and image.shape[2] in [3, 4]: From 2107ab24a93d9138f677008ba808f0bdd416b7f2 Mon Sep 17 00:00:00 2001 From: arve0 Date: Fri, 13 Mar 2015 17:42:38 +0100 Subject: [PATCH 24/42] install_requires from requirements.txt --- setup.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 0c76b698..cba8dbb7 100755 --- a/setup.py +++ b/setup.py @@ -153,9 +153,7 @@ if __name__ == "__main__": ], configuration=configuration, - install_requires=[ - "six>=%s" % DEPENDENCIES['six'] - ], + install_requires=[dep for dep in DEPENDENCIES], packages=setuptools.find_packages(exclude=['doc']), include_package_data=True, zip_safe=False, # the package can run out of an .egg file From 98ad6027809ae3067c23ab2fb26dd9611c4a3775 Mon Sep 17 00:00:00 2001 From: arve0 Date: Sun, 15 Mar 2015 12:51:13 +0100 Subject: [PATCH 25/42] install sphinx before running tests in travis --- tools/travis_before_install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/travis_before_install.sh b/tools/travis_before_install.sh index f98e48de..9b251941 100755 --- a/tools/travis_before_install.sh +++ b/tools/travis_before_install.sh @@ -41,7 +41,7 @@ else fi source ~/venv/bin/activate -retry pip install wheel flake8 coveralls nose +retry pip install wheel flake8 coveralls nose sphinx # install system tk for matplotlib sudo apt-get install python-tk From 3c6e00083f944ac7cc2fb822fadb788722df3b16 Mon Sep 17 00:00:00 2001 From: arve0 Date: Tue, 17 Mar 2015 10:59:20 +0100 Subject: [PATCH 26/42] add some more magic --- tools/travis_before_install.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/travis_before_install.sh b/tools/travis_before_install.sh index 9b251941..b9a34059 100755 --- a/tools/travis_before_install.sh +++ b/tools/travis_before_install.sh @@ -46,6 +46,8 @@ retry pip install wheel flake8 coveralls nose sphinx # install system tk for matplotlib sudo apt-get install python-tk +# try to solve #1426 +sudo apt-get install --reinstall python-pkg-resources # on Python 3.2, use matplotlib 1.3.1 if [[ $TRAVIS_PYTHON_VERSION == 3.2 ]]; then From 8af43739c42f69f9b60bdb8443ba73a42f31d1ab Mon Sep 17 00:00:00 2001 From: Eric Dill Date: Wed, 18 Mar 2015 17:30:43 -0400 Subject: [PATCH 27/42] TST: Barn-door testing of SaveButtons clicks The canny_simple.py demo in viewer_examples/plugins has a save button that raises an AttributeError in PIL because the button click is passing 'False' to the SaveButtons.save_to_file function when it expects a filename or None. --- skimage/viewer/tests/test_widgets.py | 5 +++++ skimage/viewer/widgets/history.py | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/skimage/viewer/tests/test_widgets.py b/skimage/viewer/tests/test_widgets.py index 66b86fa4..8d0e05e0 100644 --- a/skimage/viewer/tests/test_widgets.py +++ b/skimage/viewer/tests/test_widgets.py @@ -101,6 +101,11 @@ def test_save_buttons(): timer = QtCore.QTimer() timer.singleShot(100, QtGui.QApplication.quit) + # exercise the button clicks + sv.save_stack.click() + sv.save_file.click() + + # call the save functions directly sv.save_to_stack() with expected_warnings(['precision loss']): sv.save_to_file(filename) diff --git a/skimage/viewer/widgets/history.py b/skimage/viewer/widgets/history.py index 3b7f58b0..6229e525 100644 --- a/skimage/viewer/widgets/history.py +++ b/skimage/viewer/widgets/history.py @@ -80,9 +80,9 @@ class SaveButtons(BaseWidget): notify(msg) def save_to_file(self, filename=None): - if filename is None: + if not filename: filename = dialogs.save_file_dialog() - if filename is None: + if not filename: return image = self.plugin.filtered_image if image.dtype == np.bool: From 45f21d3941c53aeeb027a4871fbc49de1da3c873 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 20 Mar 2015 19:11:29 -0500 Subject: [PATCH 28/42] Fix handling of ImageCollection indexing and add test --- skimage/io/collection.py | 11 +++++++---- skimage/io/tests/test_freeimage.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index 49d6aa25..838a9f90 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -254,13 +254,16 @@ class ImageCollection(object): if ((self.conserve_memory and n != self._cached) or (self.data[idx] is None)): + kwargs = self.load_func_kwargs if self._frame_index: fname, img_num = self._frame_index[n] - self.data[idx] = self.load_func(fname, img_num=img_num, - **self.load_func_kwargs) + if img_num > 0: + self.data[idx] = self.load_func(fname, img_num=img_num, + **kwargs) + else: + self.data[idx] = self.load_func(fname, **kwargs) else: - self.data[idx] = self.load_func(self.files[n], - **self.load_func_kwargs) + self.data[idx] = self.load_func(self.files[n], **kwargs) self._cached = n return self.data[idx] diff --git a/skimage/io/tests/test_freeimage.py b/skimage/io/tests/test_freeimage.py index 81f8058a..22e09709 100644 --- a/skimage/io/tests/test_freeimage.py +++ b/skimage/io/tests/test_freeimage.py @@ -1,6 +1,7 @@ import os import skimage as si import skimage.io as sio +from skimage import data_dir import numpy as np from numpy.testing import * @@ -12,6 +13,7 @@ try: FI_available = True sio.use_plugin('freeimage') except RuntimeError: + raise FI_available = False np.random.seed(0) @@ -112,5 +114,13 @@ def test_metadata(): assert meta[1][('EXIF_MAIN', 'Software')].startswith('I') +@skipif(not FI_available) +def test_collection(): + pattern = [os.path.join(data_dir, pic) + for pic in ['camera.png', 'color.png']] + images = sio.ImageCollection(pattern) + assert len(images) == 2 + assert len(images[:]) == 2 + if __name__ == "__main__": run_module_suite() From 80555a2bdbf01d229cf0704dcb817ae14c5eb6fe Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 20 Mar 2015 19:14:25 -0500 Subject: [PATCH 29/42] Add a note to the docstring --- skimage/io/collection.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index 838a9f90..e8cc0656 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -135,7 +135,8 @@ class ImageCollection(object): ic = ImageCollection('/tmp/*.png', load_func=imread_convert) For files with multiple images, the images will be flattened into a list - and added to the list of available images. + and added to the list of available images. In this case, ``load_func`` + should accept the keyword argument ``img_num``. Examples -------- From 4344817c70b914f5de2ac16058947d92ccd0ecab Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Fri, 20 Mar 2015 19:35:17 -0500 Subject: [PATCH 30/42] Remove debug error raise --- skimage/io/tests/test_freeimage.py | 1 - 1 file changed, 1 deletion(-) diff --git a/skimage/io/tests/test_freeimage.py b/skimage/io/tests/test_freeimage.py index 22e09709..7c04bee5 100644 --- a/skimage/io/tests/test_freeimage.py +++ b/skimage/io/tests/test_freeimage.py @@ -13,7 +13,6 @@ try: FI_available = True sio.use_plugin('freeimage') except RuntimeError: - raise FI_available = False np.random.seed(0) From a51d49abe6b3a39b4d801cdbfbdfd87bf94c051d Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 21 Mar 2015 09:31:05 -0500 Subject: [PATCH 31/42] Always use _find_images() --- skimage/io/collection.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index e8cc0656..a8a890f4 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -163,11 +163,10 @@ class ImageCollection(object): for pattern in load_pattern: self._files.extend(glob(pattern)) self._files = sorted(self._files, key=alphanumeric_key) - self._numframes = self._find_images() else: self._files = load_pattern - self._numframes = len(load_pattern) - self._frame_index = None + + self._numframes = self._find_images() if conserve_memory: memory_slots = 1 From caea879bfc0e0838024ec49aefc87c8d62fb26b8 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sat, 21 Mar 2015 09:31:34 -0500 Subject: [PATCH 32/42] More specific test in freeimage --- skimage/io/tests/test_freeimage.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/skimage/io/tests/test_freeimage.py b/skimage/io/tests/test_freeimage.py index 7c04bee5..fd5af343 100644 --- a/skimage/io/tests/test_freeimage.py +++ b/skimage/io/tests/test_freeimage.py @@ -116,10 +116,12 @@ def test_metadata(): @skipif(not FI_available) def test_collection(): pattern = [os.path.join(data_dir, pic) - for pic in ['camera.png', 'color.png']] + for pic in ['camera.png', 'color.png', 'multipage.tif']] images = sio.ImageCollection(pattern) - assert len(images) == 2 - assert len(images[:]) == 2 + assert len(images) == 4 + assert len(images[:]) == 4 + # this will fail as freeimage cannot load multi-image tifs + assert_raises(TypeError, images.__getitem__, 3) if __name__ == "__main__": run_module_suite() From 73b19427515f4fa6768fa9374bd681a4d202273d Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 23 Mar 2015 15:35:17 -0500 Subject: [PATCH 33/42] Do not attempt to use _frame_index for exotic load_patterns --- skimage/io/collection.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index a8a890f4..aab7cb86 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -163,10 +163,11 @@ class ImageCollection(object): for pattern in load_pattern: self._files.extend(glob(pattern)) self._files = sorted(self._files, key=alphanumeric_key) + self._numframes = self._find_images() else: self._files = load_pattern - - self._numframes = self._find_images() + self._numframes = len(self._files) + self._frame_index = None if conserve_memory: memory_slots = 1 From 9ef99d0bb1a48ae7902f4aee9e4045331dd4fb68 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 23 Mar 2015 19:33:57 -0500 Subject: [PATCH 34/42] Fix freeimage collection test --- skimage/io/tests/test_freeimage.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/skimage/io/tests/test_freeimage.py b/skimage/io/tests/test_freeimage.py index fd5af343..238229d1 100644 --- a/skimage/io/tests/test_freeimage.py +++ b/skimage/io/tests/test_freeimage.py @@ -117,11 +117,13 @@ def test_metadata(): def test_collection(): pattern = [os.path.join(data_dir, pic) for pic in ['camera.png', 'color.png', 'multipage.tif']] + images = sio.ImageCollection(pattern[:-1]) + assert len(images) == 2 + assert len(images[:]) == 2 + images = sio.ImageCollection(pattern) - assert len(images) == 4 - assert len(images[:]) == 4 - # this will fail as freeimage cannot load multi-image tifs - assert_raises(TypeError, images.__getitem__, 3) + assert len(images) == 3 + assert len(images[:]) == 3 if __name__ == "__main__": run_module_suite() From 94d987ddcbacf07ef5785af0ab60d48aa823bf00 Mon Sep 17 00:00:00 2001 From: arve0 Date: Tue, 24 Mar 2015 19:25:33 +0100 Subject: [PATCH 35/42] close conda install code string --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b7ae96d1..f1338716 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - **Debian/Ubuntu:** ``sudo apt-get install python-skimage`` - **OSX:** ``pip install scikit-image`` -- **Anaconda:** ``conda install scikit-image +- **Anaconda:** ``conda install scikit-image`` - **Windows:** Download [Windows binaries](http://www.lfd.uci.edu/~gohlke/pythonlibs/#scikits.image) Also see From 77d725893ee6c6db25ce8e94ea363f00fb4ac7a7 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 25 Mar 2015 20:18:08 -0500 Subject: [PATCH 36/42] Fix for broken setuptools --- tools/travis_before_install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/travis_before_install.sh b/tools/travis_before_install.sh index b9a34059..7036dffb 100755 --- a/tools/travis_before_install.sh +++ b/tools/travis_before_install.sh @@ -36,6 +36,7 @@ if [[ $TRAVIS_PYTHON_VERSION == 2.7* ]]; then sed -i 's/cython>=/cython==/g' requirements.txt sed -i 's/networkx>=/networkx==/g' requirements.txt sed -i '/pillow/d' requirements.txt + sudo apt-get install --reinstall python-pkg-resources else virtualenv -p python --system-site-packages ~/venv fi From adac822ee97eb452ba6ac67fba28e77a3e3ff306 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 25 Mar 2015 22:16:51 -0500 Subject: [PATCH 37/42] =?UTF-8?q?Fix=20setup=20to=20allow=20installing=20f?= =?UTF-8?q?rom=20PyPI=20=E2=89=88=20Fix=20setup=20to=20allow=20installing?= =?UTF-8?q?=20from=20PyPi=20Another=20attempt=20at=20fixing=20the=20setupt?= =?UTF-8?q?ools=20problem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix pip incantation Fix typo Try updating setuptools too Try upgrading pip and setuptools after venv install Rule out install_requires as the source of the problem Try just requiring the ones that can be built from source Use explicit install_requires and move version checks to after setup runs Clean up installation for PyPI compatiblity Dead end commit Fix travis to match new installation procedure Put build_versions check after install Fix travis syntax Switch to lower-case cython in version check Another attempt Another fix Fix syntax error Make header executable Build inplace on py27 Fix finding of source code version in sphinx Fix travis syntax Import setuptools after install Fix the version check in sphinx Work around setuptools bug in 2.7 Fix handling of Cython requirement and update release notes Switch to one Appveyor build and update build method Add cython back to install_requires Remove debug lines Another try for appveyor install Another attempt at setuptools and Appveyor Do not let intermittent apt-get failures crash the build Fix typo Another appveyor attempt More fixes for setuptools and Appveyor Yet another setuptools/appveyor attempt Put requirements.txt back in order Fix typo Fix readlines function call Try not using a venv for python 2.7 Fix syntax Try the provided venv for py27 Remove --user Remove debug info Another try for python27 fix Try again Do not use install_requires with numpy/scipy Try just avoiding scipy Try removing scipy (numpy was before) Avoid both scipy and numpy Fix qt install on 27 Fix qt install on 27 agin Revert the scripts to their previous condition Revert file permission changes Undo changes to requirements.txt --- .travis.yml | 2 +- RELEASE.txt | 2 +- appveyor.yml | 19 ++--- doc/source/conf.py | 4 +- doc/tools/build_modref_templates.py | 6 +- setup.py | 112 ++++++++-------------------- skimage/__init__.py | 8 +- tools/travis_before_install.sh | 5 +- 8 files changed, 52 insertions(+), 106 deletions(-) mode change 100755 => 100644 setup.py diff --git a/.travis.yml b/.travis.yml index a46b7171..14dd7c30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ python: - 3.4 before_install: - - sudo apt-get update + - sudo apt-get update; true - source tools/travis_before_install.sh - which python; python --version diff --git a/RELEASE.txt b/RELEASE.txt index 66860662..be5c1da3 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -15,7 +15,7 @@ How to make a new release of ``skimage`` 3. Copy ``doc/release/release_template.txt`` to ``doc/release/release_dev.txt`` for the next release. -- Update the version number in ``setup.py`` and ``bento.info`` and commit +- Update the version number in ``skimage/__init__.py`` and ``bento.info`` and commit - Update the docs: diff --git a/appveyor.yml b/appveyor.yml index df1ffd3e..0bd10075 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -13,17 +13,18 @@ environment: PYTHON_VERSION: "2.7" PYTHON_ARCH: "32" - - PYTHON: "C:\\Python27_64" - PYTHON_VERSION: "2.7" - PYTHON_ARCH: "64" + # disable other builds until they can be run in parallel + #- PYTHON: "C:\\Python27_64" + # PYTHON_VERSION: "2.7" + # PYTHON_ARCH: "64" - - PYTHON: "C:\\Python34_32" - PYTHON_VERSION: "3.4.2" - PYTHON_ARCH: "32" + #- PYTHON: "C:\\Python34_32" + # PYTHON_VERSION: "3.4.2" + # PYTHON_ARCH: "32" - - PYTHON: "C:\\Python24_64" - PYTHON_VERSION: "3.4.2" - PYTHON_ARCH: "64" + #- PYTHON: "C:\\Python24_64" + # PYTHON_VERSION: "3.4.2" + # PYTHON_ARCH: "64" install: # Install Python (from the official .msi of http://python.org) and pip when diff --git a/doc/source/conf.py b/doc/source/conf.py index 94904305..794df662 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -68,10 +68,10 @@ copyright = '2013, the scikit-image team' # # The short X.Y version. -setup_lines = open('../../setup.py').readlines() +setup_lines = open('../../skimage/__init__.py').readlines() version = 'vUndefined' for l in setup_lines: - if l.startswith('VERSION'): + if l.startswith('__version__'): version = l.split("'")[1] break diff --git a/doc/tools/build_modref_templates.py b/doc/tools/build_modref_templates.py index e83ce980..2d959252 100644 --- a/doc/tools/build_modref_templates.py +++ b/doc/tools/build_modref_templates.py @@ -37,10 +37,10 @@ if __name__ == '__main__': installed_version = V(module.__version__) - setup_lines = open('../setup.py').readlines() + source_lines = open('../skimage/__init__.py').readlines() version = 'vUndefined' - for l in setup_lines: - if l.startswith('VERSION'): + for l in source_lines: + if l.startswith('__version__'): source_version = V(l.split("'")[1]) break diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index cba8dbb7..8a938da5 --- a/setup.py +++ b/setup.py @@ -17,28 +17,41 @@ MAINTAINER_EMAIL = 'stefan@sun.ac.za' URL = 'http://scikit-image.org' LICENSE = 'Modified BSD' DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image' -VERSION = '0.12dev' -PYTHON_VERSION = (2, 6) import os import sys import setuptools from distutils.command.build_py import build_py -from distutils.version import LooseVersion -# These are manually checked. -# These packages are sometimes installed outside of the setuptools scope -DEPENDENCIES = {} -with open('requirements.txt', 'rb') as fid: - data = fid.read().decode('utf-8', 'replace') -for line in data.splitlines(): - pkg, _, version_info = line.replace('==', '>=').partition('>=') - # Only require Cython if we have a developer checkout - if pkg.lower() == 'cython' and not VERSION.endswith('dev'): - continue - DEPENDENCIES[str(pkg).lower()] = str(version_info) +with open('skimage/__init__.py') as fid: + for line in fid: + if line.startswith('__version__'): + VERSION = line.strip().split()[-1][1:-1] + break + +with open('requirements.txt') as fid: + INSTALL_REQUIRES = [l.strip() for l in fid.readlines() if l] + +# development versions do not have the cythonized files +if VERSION.endswith('dev'): + SETUP_REQUIRES = [r for r in INSTALL_REQUIRES if r.startswith('cython')] +else: + INSTALL_REQUIRES = [r for r in INSTALL_REQUIRES + if not r.startswith('cython')] + SETUP_REQUIRES = [] + + +# list requirements for PyPI +REQUIRES = [r.replace('>=', ' (>= ') + ')' + for r in INSTALL_REQUIRES + SETUP_REQUIRES] +REQUIRES = [r.replace('==', ' (== ') for r in REQUIRES] + + +# do not attempt to install numpy and scipy until they have eggs available +INSTALL_REQUIRES = [r for r in INSTALL_REQUIRES + if not r.startswith(('scipy', 'numpy'))] def configuration(parent_package='', top_path=None): @@ -59,72 +72,11 @@ def configuration(parent_package='', top_path=None): return config -def write_version_py(filename='skimage/version.py'): - template = """# THIS FILE IS GENERATED FROM THE SKIMAGE SETUP.PY -version='%s' -""" - - try: - vfile = open(os.path.join(os.path.dirname(__file__), - filename), 'w') - vfile.write(template % VERSION) - - except IOError: - raise IOError("Could not open/write to skimage/version.py - did you " - "install using sudo in the past? If so, run\n" - "sudo chown -R your_username ./*\n" - "from package root to fix permissions, and try again.") - - finally: - vfile.close() - - -def get_package_version(package): - for version_attr in ('__version__', 'VERSION', 'version'): - version_info = getattr(package, version_attr, None) - if version_info and str(version_attr) == version_attr: - return str(version_info) - - -def check_requirements(): - if sys.version_info < PYTHON_VERSION: - raise SystemExit('You need Python version %d.%d or later.' \ - % PYTHON_VERSION) - for (package_name, min_version) in DEPENDENCIES.items(): - if package_name == 'cython': - package_name = 'Cython' - dep_error = '' - if package_name.lower() == 'pillow': - package_name = 'PIL.Image' - min_version = '1.1.7' - try: - package = __import__(package_name, - fromlist=[package_name.rpartition('.')[0]]) - except ImportError: - dep_error = ('You need `%s` version %s or later.' - % (package_name, min_version)) - else: - if package_name == 'PIL': - package_version = package.PILLOW_VERSION - else: - package_version = get_package_version(package) - - if LooseVersion(min_version) > LooseVersion(package_version): - dep_error = ('You need `%s` version %s or later,' - 'found version %s.' - % (package_name, min_version, - package_version)) - if dep_error: - raise ImportError(dep_error) - - if __name__ == "__main__": - - check_requirements() - - write_version_py() - + # purposely fail loudly if numpy or scipy are not available from numpy.distutils.core import setup + import scipy + setup( name=DISTNAME, description=DESCRIPTION, @@ -153,7 +105,9 @@ if __name__ == "__main__": ], configuration=configuration, - install_requires=[dep for dep in DEPENDENCIES], + setup_requires=SETUP_REQUIRES, + install_requires=INSTALL_REQUIRES, + requires=REQUIRES, packages=setuptools.find_packages(exclude=['doc']), include_package_data=True, zip_safe=False, # the package can run out of an .egg file diff --git a/skimage/__init__.py b/skimage/__init__.py index 8f386682..52db27a3 100644 --- a/skimage/__init__.py +++ b/skimage/__init__.py @@ -64,13 +64,7 @@ import warnings as _warnings pkg_dir = _osp.abspath(_osp.dirname(__file__)) data_dir = _osp.join(pkg_dir, 'data') -try: - from .version import version as __version__ -except ImportError: - __version__ = "unbuilt-dev" -else: - del version - +__version__ = '0.12dev' try: _imp.find_module('nose') diff --git a/tools/travis_before_install.sh b/tools/travis_before_install.sh index 7036dffb..f98e48de 100755 --- a/tools/travis_before_install.sh +++ b/tools/travis_before_install.sh @@ -36,19 +36,16 @@ if [[ $TRAVIS_PYTHON_VERSION == 2.7* ]]; then sed -i 's/cython>=/cython==/g' requirements.txt sed -i 's/networkx>=/networkx==/g' requirements.txt sed -i '/pillow/d' requirements.txt - sudo apt-get install --reinstall python-pkg-resources else virtualenv -p python --system-site-packages ~/venv fi source ~/venv/bin/activate -retry pip install wheel flake8 coveralls nose sphinx +retry pip install wheel flake8 coveralls nose # install system tk for matplotlib sudo apt-get install python-tk -# try to solve #1426 -sudo apt-get install --reinstall python-pkg-resources # on Python 3.2, use matplotlib 1.3.1 if [[ $TRAVIS_PYTHON_VERSION == 3.2 ]]; then From eed18b803f0b794331fad0d2a7527d1092b5d391 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Sun, 29 Mar 2015 15:33:41 -0500 Subject: [PATCH 38/42] Another random warning guard --- skimage/_shared/testing.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/skimage/_shared/testing.py b/skimage/_shared/testing.py index 1c41221b..f202fbff 100644 --- a/skimage/_shared/testing.py +++ b/skimage/_shared/testing.py @@ -161,7 +161,7 @@ def mono_check(plugin, fmt='png'): else: testing.assert_allclose(r3, img_as_uint(img)) - with expected_warnings(['precision loss']): + with expected_warnings(['precision loss|unclosed file']): img4 = img_as_int(img) if fmt.lower() in (('tif', 'tiff')): img4 -= 100 @@ -182,7 +182,7 @@ def setup_test(): """Default package level setup routine for skimage tests. Import packages known to raise errors, and then - force warnings to raise errors. + force warnings to raise errors. Set a random seed """ warnings.simplefilter('default') @@ -190,7 +190,7 @@ def setup_test(): from scipy.io import loadmat from skimage import viewer, filter np.random.seed(0) - warnings.simplefilter('error') + warnings.simplefilter('error') def teardown_test(): From e531e57124a71739f834c23ea930cfb40cb823d3 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Wed, 25 Mar 2015 22:22:06 -0500 Subject: [PATCH 39/42] Only index tif and gif files in collection --- skimage/io/collection.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index aab7cb86..cdcb31d6 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -201,7 +201,7 @@ class ImageCollection(object): if fname.lower().endswith(('.tiff', '.tif')): img = TiffFile(fname) index += [(fname, i) for i in range(len(img.pages))] - else: + elif fname.lower().endswith('gif'): im = Image.open(fname) try: # this will raise an IOError if the file is not readable @@ -221,6 +221,8 @@ class ImageCollection(object): i += 1 if hasattr(im, 'fp') and im.fp: im.fp.close() + else: + index += (fname, 0) self._frame_index = index return len(index) From ad8c94fcaf6c6225ab1ac9686a64417652dd777c Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Mon, 30 Mar 2015 21:41:44 -0500 Subject: [PATCH 40/42] Fix handling of non-gif and tiff files --- skimage/io/collection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index cdcb31d6..b36c95f4 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -135,7 +135,7 @@ class ImageCollection(object): ic = ImageCollection('/tmp/*.png', load_func=imread_convert) For files with multiple images, the images will be flattened into a list - and added to the list of available images. In this case, ``load_func`` + and added to the list of available images. In this case, ``load_func`` should accept the keyword argument ``img_num``. Examples @@ -222,7 +222,7 @@ class ImageCollection(object): if hasattr(im, 'fp') and im.fp: im.fp.close() else: - index += (fname, 0) + index += [(fname, 0)] self._frame_index = index return len(index) From 62e82ccf49d37307e3fcabd137eae32f9cd596b2 Mon Sep 17 00:00:00 2001 From: Steven Silvester Date: Tue, 31 Mar 2015 20:54:57 -0500 Subject: [PATCH 41/42] Do not read in the whole array --- skimage/io/collection.py | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/skimage/io/collection.py b/skimage/io/collection.py index b36c95f4..8812740e 100644 --- a/skimage/io/collection.py +++ b/skimage/io/collection.py @@ -201,29 +201,23 @@ class ImageCollection(object): if fname.lower().endswith(('.tiff', '.tif')): img = TiffFile(fname) index += [(fname, i) for i in range(len(img.pages))] - elif fname.lower().endswith('gif'): - im = Image.open(fname) + else: try: - # this will raise an IOError if the file is not readable - im.getdata()[0] - except IOError: - site = "http://pillow.readthedocs.org/en/latest/installation.html#external-libraries" - raise ValueError( - 'Could not load "%s"\nPlease see documentation at: %s' % (fname, site)) - else: - i = 0 - while True: - try: - im.seek(i) - except EOFError: - break - index.append((fname, i)) - i += 1 + im = Image.open(fname) + im.seek(0) + except (IOError, OSError): + index.append([fname, i]) + continue + i = 0 + while True: + try: + im.seek(i) + except EOFError: + break + index.append((fname, i)) + i += 1 if hasattr(im, 'fp') and im.fp: im.fp.close() - else: - index += [(fname, 0)] - self._frame_index = index return len(index) From 76b7e426d4acb206b68bd314040d59baa68b14ec Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Wed, 1 Apr 2015 01:26:38 -0700 Subject: [PATCH 42/42] Set version to 0.11.3 --- bento.info | 2 +- setup.py | 1 - skimage/__init__.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/bento.info b/bento.info index cba403d9..8587db3f 100644 --- a/bento.info +++ b/bento.info @@ -1,5 +1,5 @@ Name: scikit-image -Version: 0.12.dev0 +Version: 0.11.3 Summary: Image processing routines for SciPy Url: http://scikit-image.org DownloadUrl: http://github.com/scikit-image/scikit-image diff --git a/setup.py b/setup.py index 8a938da5..9e5d1444 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,6 @@ LICENSE = 'Modified BSD' DOWNLOAD_URL = 'http://github.com/scikit-image/scikit-image' import os -import sys import setuptools from distutils.command.build_py import build_py diff --git a/skimage/__init__.py b/skimage/__init__.py index 52db27a3..2ec70944 100644 --- a/skimage/__init__.py +++ b/skimage/__init__.py @@ -64,7 +64,7 @@ import warnings as _warnings pkg_dir = _osp.abspath(_osp.dirname(__file__)) data_dir = _osp.join(pkg_dir, 'data') -__version__ = '0.12dev' +__version__ = '0.11.3' try: _imp.find_module('nose')