mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-28 23:42:02 +08:00
9e8f91930e
Start handling warnings in data, exposure, and draw Add a known_warning decorator and suppress warnings in color pkg Use the existing all_warnings context manager Raise warnings in data Raise warnings in draw Raise warnings in exposure Suppress warnings in exposure tests Add comments about warning suppressions Raise warnings in feature Fix warnings in filter package Add warning handling to graph Handle warnings in io package
185 lines
5.1 KiB
Python
185 lines
5.1 KiB
Python
"""Testing utilities."""
|
|
|
|
|
|
import os
|
|
import re
|
|
from tempfile import NamedTemporaryFile
|
|
|
|
from skimage import (
|
|
data, io, img_as_uint, img_as_float, img_as_int, img_as_ubyte)
|
|
from numpy import testing
|
|
import numpy as np
|
|
from skimage._shared.utils import all_warnings
|
|
|
|
|
|
SKIP_RE = re.compile("(\s*>>>.*?)(\s*)#\s*skip\s+if\s+(.*)$")
|
|
|
|
|
|
def _assert_less(a, b, msg=None):
|
|
message = "%r is not lower than %r" % (a, b)
|
|
if msg is not None:
|
|
message += ": " + msg
|
|
assert a < b, message
|
|
|
|
|
|
def _assert_greater(a, b, msg=None):
|
|
message = "%r is not greater than %r" % (a, b)
|
|
if msg is not None:
|
|
message += ": " + msg
|
|
assert a > b, message
|
|
|
|
|
|
try:
|
|
from nose.tools import assert_less
|
|
except ImportError:
|
|
assert_less = _assert_less
|
|
|
|
try:
|
|
from nose.tools import assert_greater
|
|
except ImportError:
|
|
assert_greater = _assert_greater
|
|
|
|
|
|
def doctest_skip_parser(func):
|
|
""" Decorator replaces custom skip test markup in doctests
|
|
|
|
Say a function has a docstring::
|
|
|
|
>>> something # skip if not HAVE_AMODULE
|
|
>>> something + else
|
|
>>> something # skip if HAVE_BMODULE
|
|
|
|
This decorator will evaluate the expression after ``skip if``. If this
|
|
evaluates to True, then the comment is replaced by ``# doctest: +SKIP``. If
|
|
False, then the comment is just removed. The expression is evaluated in the
|
|
``globals`` scope of `func`.
|
|
|
|
For example, if the module global ``HAVE_AMODULE`` is False, and module
|
|
global ``HAVE_BMODULE`` is False, the returned function will have docstring::
|
|
|
|
>>> something # doctest: +SKIP
|
|
>>> something + else
|
|
>>> something
|
|
|
|
"""
|
|
lines = func.__doc__.split('\n')
|
|
new_lines = []
|
|
for line in lines:
|
|
match = SKIP_RE.match(line)
|
|
if match is None:
|
|
new_lines.append(line)
|
|
continue
|
|
code, space, expr = match.groups()
|
|
|
|
try:
|
|
# Works as a function decorator
|
|
if eval(expr, func.__globals__):
|
|
code = code + space + "# doctest: +SKIP"
|
|
except AttributeError:
|
|
# Works as a class decorator
|
|
if eval(expr, func.__init__.__globals__):
|
|
code = code + space + "# doctest: +SKIP"
|
|
|
|
new_lines.append(code)
|
|
func.__doc__ = "\n".join(new_lines)
|
|
return func
|
|
|
|
|
|
def roundtrip(img, plugin, suffix):
|
|
"""Save and read an image using a specified plugin"""
|
|
if not '.' in suffix:
|
|
suffix = '.' + suffix
|
|
temp_file = NamedTemporaryFile(suffix=suffix, delete=False)
|
|
temp_file.close()
|
|
fname = temp_file.name
|
|
io.imsave(fname, img, plugin=plugin)
|
|
new = io.imread(fname, plugin=plugin)
|
|
try:
|
|
os.remove(fname)
|
|
except Exception:
|
|
pass
|
|
return new
|
|
|
|
|
|
def color_check(plugin, fmt='png'):
|
|
"""Check roundtrip behavior for color images.
|
|
|
|
All major input types should be handled as ubytes and read
|
|
back correctly.
|
|
"""
|
|
img = img_as_ubyte(data.chelsea())
|
|
r1 = roundtrip(img, plugin, fmt)
|
|
testing.assert_allclose(img, r1)
|
|
|
|
img2 = img > 128
|
|
r2 = roundtrip(img2, plugin, fmt)
|
|
testing.assert_allclose(img2.astype(np.uint8), r2)
|
|
|
|
img3 = img_as_float(img)
|
|
with all_warnings(): # precision loss
|
|
r3 = roundtrip(img3, plugin, fmt)
|
|
testing.assert_allclose(r3, img)
|
|
|
|
with all_warnings(): # precision loss
|
|
img4 = img_as_int(img)
|
|
if fmt.lower() in (('tif', 'tiff')):
|
|
img4 -= 100
|
|
with all_warnings(): # sign loss
|
|
r4 = roundtrip(img4, plugin, fmt)
|
|
testing.assert_allclose(r4, img4)
|
|
else:
|
|
with all_warnings(): # sign loss
|
|
r4 = roundtrip(img4, plugin, fmt)
|
|
testing.assert_allclose(r4, img_as_ubyte(img4))
|
|
|
|
img5 = img_as_uint(img)
|
|
with all_warnings(): # precision loss
|
|
r5 = roundtrip(img5, plugin, fmt)
|
|
testing.assert_allclose(r5, img)
|
|
|
|
|
|
def mono_check(plugin, fmt='png'):
|
|
"""Check the roundtrip behavior for images that support most types.
|
|
|
|
All major input types should be handled.
|
|
"""
|
|
|
|
img = img_as_ubyte(data.moon())
|
|
r1 = roundtrip(img, plugin, fmt)
|
|
testing.assert_allclose(img, r1)
|
|
|
|
img2 = img > 128
|
|
r2 = roundtrip(img2, plugin, fmt)
|
|
testing.assert_allclose(img2.astype(np.uint8), r2)
|
|
|
|
img3 = img_as_float(img)
|
|
with all_warnings(): # precision loss
|
|
r3 = roundtrip(img3, plugin, fmt)
|
|
if r3.dtype.kind == 'f':
|
|
testing.assert_allclose(img3, r3)
|
|
else:
|
|
testing.assert_allclose(r3, img_as_uint(img))
|
|
|
|
with all_warnings(): # precision loss
|
|
img4 = img_as_int(img)
|
|
if fmt.lower() in (('tif', 'tiff')):
|
|
img4 -= 100
|
|
with all_warnings(): # sign loss
|
|
r4 = roundtrip(img4, plugin, fmt)
|
|
testing.assert_allclose(r4, img4)
|
|
else:
|
|
with all_warnings(): # sign loss
|
|
r4 = roundtrip(img4, plugin, fmt)
|
|
testing.assert_allclose(r4, img_as_uint(img4))
|
|
|
|
img5 = img_as_uint(img)
|
|
r5 = roundtrip(img5, plugin, fmt)
|
|
testing.assert_allclose(r5, img5)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
color_check('pil')
|
|
mono_check('pil')
|
|
mono_check('pil', 'bmp')
|
|
mono_check('pil', 'tiff')
|