Skip to content

Commit e8b9d82

Browse files
committed
TST+RF: adapt to new numpy memmap behavior
Numpy memmap behavior changed in upcoming 1.12. Adapt the tests to the new behavior when we detect it. In the process, make the test function more explicit in input arguments and document the test function.
1 parent 316a966 commit e8b9d82

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

nibabel/tests/test_arrayproxy.py

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from numpy.testing import assert_array_equal, assert_array_almost_equal
2424
from nose.tools import (assert_true, assert_false, assert_equal,
2525
assert_not_equal, assert_raises)
26+
from nibabel.testing import VIRAL_MEMMAP
2627

2728
from .test_fileslice import slicer_samples
2829

@@ -182,10 +183,37 @@ def test_mmap():
182183
check_mmap(hdr, hdr.get_data_offset(), ArrayProxy)
183184

184185

185-
def check_mmap(hdr, offset, proxy_class, check_mode=True):
186+
def check_mmap(hdr, offset, proxy_class,
187+
has_scaling=False,
188+
unscaled_is_view=True):
189+
""" Assert that array proxies return memory maps as expected
190+
191+
Parameters
192+
----------
193+
hdr : object
194+
Image header instance
195+
offset : int
196+
Offset in bytes of image data in file (that we will write)
197+
proxy_class : class
198+
Class of image array proxy to test
199+
has_scaling : {False, True}
200+
True if the `hdr` says to apply scaling to the output data, False
201+
otherwise.
202+
unscaled_is_view : {True, False}
203+
True if getting the unscaled data returns a view of the array. If
204+
False, then type of returned array will depend on whether numpy has the
205+
old viral (< 1.12) memmap behavior (returns memmap) or the new behavior
206+
(returns ndarray). See: https://github.com/numpy/numpy/pull/7406
207+
"""
186208
shape = hdr.get_data_shape()
187209
arr = np.arange(np.prod(shape), dtype=hdr.get_data_dtype()).reshape(shape)
188210
fname = 'test.bin'
211+
# Whether unscaled array memory backed by memory map (regardless of what
212+
# numpy says).
213+
unscaled_really_mmap = unscaled_is_view
214+
# Whether scaled array memory backed by memory map (regardless of what
215+
# numpy says).
216+
scaled_really_mmap = unscaled_really_mmap and not has_scaling
189217
with InTemporaryDirectory():
190218
with open(fname, 'wb') as fobj:
191219
fobj.write(b' ' * offset)
@@ -205,13 +233,17 @@ def check_mmap(hdr, offset, proxy_class, check_mode=True):
205233
prox = proxy_class(fname, hdr, **kwargs)
206234
unscaled = prox.get_unscaled()
207235
back_data = np.asanyarray(prox)
236+
unscaled_is_mmap = isinstance(unscaled, np.memmap)
237+
back_is_mmap = isinstance(back_data, np.memmap)
208238
if expected_mode is None:
209-
assert_false(isinstance(unscaled, np.memmap))
210-
assert_false(isinstance(back_data, np.memmap))
239+
assert_false(unscaled_is_mmap)
240+
assert_false(back_is_mmap)
211241
else:
212-
assert_true(isinstance(unscaled, np.memmap))
213-
assert_true(isinstance(back_data, np.memmap))
214-
if check_mode:
242+
assert_equal(unscaled_is_mmap,
243+
VIRAL_MEMMAP or unscaled_really_mmap)
244+
assert_equal(back_is_mmap,
245+
VIRAL_MEMMAP or scaled_really_mmap)
246+
if scaled_really_mmap:
215247
assert_equal(back_data.mode, expected_mode)
216248
del prox, back_data
217249
# Check that mmap is keyword-only

nibabel/tests/test_parrec.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,9 @@ def test_parrec_proxy():
728728
# Test PAR / REC proxy class, including mmap flags
729729
shape = (10, 20, 30, 5)
730730
hdr = FakeHeader(shape, np.int32)
731-
check_mmap(hdr, 0, PARRECArrayProxy, check_mode=False)
731+
check_mmap(hdr, 0, PARRECArrayProxy,
732+
has_scaling=True,
733+
unscaled_is_view=False)
732734

733735

734736
class TestPARRECImage(tsi.MmapImageMixin):

nibabel/tests/test_spatialimages.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
from numpy.testing import assert_array_equal, assert_array_almost_equal
2525

2626
from .test_helpers import bytesio_round_trip
27-
from ..testing import clear_and_catch_warnings, suppress_warnings
27+
from ..testing import (clear_and_catch_warnings, suppress_warnings,
28+
VIRAL_MEMMAP)
2829
from ..tmpdirs import InTemporaryDirectory
2930
from .. import load as top_load
3031

@@ -384,6 +385,13 @@ def test_load_mmap(self):
384385
('c', 'c'),
385386
('r', 'r'),
386387
(False, None)):
388+
# If the image has scaling, then numpy 1.12 will not return
389+
# a memmap, regardless of the input flags. Previous
390+
# numpies returned a memmap object, even though the array
391+
# has no mmap memory backing. See:
392+
# https://github.com/numpy/numpy/pull/7406
393+
if has_scaling and not VIRAL_MEMMAP:
394+
expected_mode = None
387395
kwargs = {}
388396
if mmap is not None:
389397
kwargs['mmap'] = mmap

0 commit comments

Comments
 (0)