mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-28 11:25:42 +08:00
Merge pull request #971 from stefanv/bug/views_are_copies
Do not allow `view_as_*` to return copies (closes #866)
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
__all__ = ['all_warnings']
|
||||
|
||||
from contextlib import contextmanager
|
||||
import sys
|
||||
import warnings
|
||||
import inspect
|
||||
|
||||
|
||||
@contextmanager
|
||||
def all_warnings():
|
||||
"""
|
||||
Context for use in testing to ensure that all warnings are raised.
|
||||
|
||||
Examples
|
||||
--------
|
||||
>>> import warnings
|
||||
>>> def foo():
|
||||
... warnings.warn(RuntimeWarning("bar"))
|
||||
|
||||
We raise the warning once, while the warning filter is set to "once".
|
||||
Hereafter, the warning is invisible, even with custom filters:
|
||||
|
||||
>>> with warnings.catch_warnings():
|
||||
... warnings.simplefilter('once')
|
||||
... foo()
|
||||
|
||||
We can now run ``foo()`` without a warning being raised:
|
||||
|
||||
>>> from numpy.testing import assert_warns
|
||||
>>> foo()
|
||||
|
||||
To catch the warning, we call in the help of ``all_warnings``:
|
||||
|
||||
>>> with all_warnings():
|
||||
... assert_warns(RuntimeWarning, foo)
|
||||
"""
|
||||
|
||||
# Whenever a warning is triggered, Python adds a __warningregistry__
|
||||
# member to the *calling* module. The exercize here is to find
|
||||
# and eradicate all those breadcrumbs that were left lying around.
|
||||
#
|
||||
# We proceed by first searching all parent calling frames and explicitly
|
||||
# clearing their warning registries (necessary for the doctests above to
|
||||
# pass). Then, we search for all submodules of skimage and clear theirs
|
||||
# as well (necessary for the skimage test suite to pass).
|
||||
|
||||
frame = inspect.currentframe()
|
||||
if frame:
|
||||
for f in inspect.getouterframes(frame):
|
||||
f[0].f_locals['__warningregistry__'] = {}
|
||||
del frame
|
||||
|
||||
for mod in list(sys.modules.values()):
|
||||
try:
|
||||
mod.__warningregistry__.clear()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
warnings.simplefilter("always")
|
||||
yield w
|
||||
@@ -4,8 +4,9 @@ import sys
|
||||
|
||||
import six
|
||||
|
||||
from ._warnings import all_warnings
|
||||
|
||||
__all__ = ['deprecated', 'get_bound_method_class']
|
||||
__all__ = ['deprecated', 'get_bound_method_class', 'all_warnings']
|
||||
|
||||
|
||||
class skimage_deprecation(Warning):
|
||||
|
||||
+22
-13
@@ -2,6 +2,7 @@ __all__ = ['view_as_blocks', 'view_as_windows']
|
||||
|
||||
import numpy as np
|
||||
from numpy.lib.stride_tricks import as_strided
|
||||
from warnings import warn
|
||||
|
||||
|
||||
def view_as_blocks(arr_in, block_shape):
|
||||
@@ -11,17 +12,17 @@ def view_as_blocks(arr_in, block_shape):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
arr_in: ndarray
|
||||
The n-dimensional input array.
|
||||
|
||||
block_shape: tuple
|
||||
arr_in : ndarray
|
||||
N-d input array.
|
||||
block_shape : tuple
|
||||
The shape of the block. Each dimension must divide evenly into the
|
||||
corresponding dimensions of `arr_in`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
arr_out: ndarray
|
||||
Block view of the input array.
|
||||
arr_out : ndarray
|
||||
Block view of the input array. If `arr_in` is non-contiguous, a copy
|
||||
is made.
|
||||
|
||||
Examples
|
||||
--------
|
||||
@@ -70,8 +71,6 @@ def view_as_blocks(arr_in, block_shape):
|
||||
[[[76, 77],
|
||||
[82, 83]]]])
|
||||
"""
|
||||
|
||||
# -- basic checks on arguments
|
||||
if not isinstance(block_shape, tuple):
|
||||
raise TypeError('block needs to be a tuple')
|
||||
|
||||
@@ -88,6 +87,11 @@ def view_as_blocks(arr_in, block_shape):
|
||||
raise ValueError("'block_shape' is not compatible with 'arr_in'")
|
||||
|
||||
# -- restride the array to build the block view
|
||||
|
||||
if not arr_in.flags.contiguous:
|
||||
warn(RuntimeWarning("Cannot provide views on a non-contiguous input "
|
||||
"array without copying."))
|
||||
|
||||
arr_in = np.ascontiguousarray(arr_in)
|
||||
|
||||
new_shape = tuple(arr_shape / block_shape) + tuple(block_shape)
|
||||
@@ -106,9 +110,9 @@ def view_as_windows(arr_in, window_shape, step=1):
|
||||
|
||||
Parameters
|
||||
----------
|
||||
arr_in: ndarray
|
||||
The n-dimensional input array.
|
||||
window_shape: tuple
|
||||
arr_in : ndarray
|
||||
N-d input array.
|
||||
window_shape : tuple
|
||||
Defines the shape of the elementary n-dimensional orthotope
|
||||
(better know as hyperrectangle [1]_) of the rolling window view.
|
||||
step : int, optional
|
||||
@@ -118,8 +122,9 @@ def view_as_windows(arr_in, window_shape, step=1):
|
||||
|
||||
Returns
|
||||
-------
|
||||
arr_out: ndarray
|
||||
(rolling) window view of the input array.
|
||||
arr_out : ndarray
|
||||
(rolling) window view of the input array. If `arr_in` is
|
||||
non-contiguous, a copy is made.
|
||||
|
||||
Notes
|
||||
-----
|
||||
@@ -228,6 +233,10 @@ def view_as_windows(arr_in, window_shape, step=1):
|
||||
raise ValueError("`window_shape` is too small")
|
||||
|
||||
# -- build rolling window view
|
||||
if not arr_in.flags.contiguous:
|
||||
warn(RuntimeWarning("Cannot provide views on a non-contiguous input "
|
||||
"array without copying."))
|
||||
|
||||
arr_in = np.ascontiguousarray(arr_in)
|
||||
|
||||
new_shape = tuple((arr_shape - window_shape) // step + 1) + \
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import numpy as np
|
||||
from nose.tools import raises
|
||||
from numpy.testing import assert_equal
|
||||
from numpy.testing import assert_equal, assert_warns
|
||||
|
||||
from skimage.util.shape import view_as_blocks, view_as_windows
|
||||
from skimage._shared.utils import all_warnings
|
||||
|
||||
|
||||
@raises(TypeError)
|
||||
@@ -131,7 +133,7 @@ def test_view_as_windows_2D():
|
||||
[17, 18, 19]]]]))
|
||||
|
||||
|
||||
def test_view_as_windows_With_skip():
|
||||
def test_view_as_windows_with_skip():
|
||||
A = np.arange(20).reshape((5, 4))
|
||||
B = view_as_windows(A, (2, 2), step=2)
|
||||
assert_equal(B, [[[[0, 1],
|
||||
@@ -147,5 +149,14 @@ def test_view_as_windows_With_skip():
|
||||
assert_equal(C.shape, (1, 1, 2, 2))
|
||||
|
||||
|
||||
def test_views_non_contiguous():
|
||||
A = np.arange(16).reshape((4, 4))
|
||||
A = A[::2, :]
|
||||
|
||||
with all_warnings():
|
||||
assert_warns(RuntimeWarning, view_as_blocks, A, (2, 2))
|
||||
assert_warns(RuntimeWarning, view_as_windows, A, (2, 2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
np.testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user