-
Notifications
You must be signed in to change notification settings - Fork 260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENH: Make layout order an initialization parameter of ArrayProxy #1131
Changes from all commits
ea68dd1
0155598
4720932
df252ca
3cfe337
dcf9566
cba4607
cff42d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,13 +15,16 @@ | |
|
||
import pickle | ||
from io import BytesIO | ||
from packaging.version import Version | ||
from ..tmpdirs import InTemporaryDirectory | ||
|
||
import numpy as np | ||
|
||
from .. import __version__ | ||
from ..arrayproxy import (ArrayProxy, is_proxy, reshape_dataobj, get_obj_dtype) | ||
from ..openers import ImageOpener | ||
from ..nifti1 import Nifti1Header | ||
from ..deprecator import ExpiredDeprecationError | ||
|
||
from unittest import mock | ||
|
||
|
@@ -57,6 +60,11 @@ def copy(self): | |
|
||
class CArrayProxy(ArrayProxy): | ||
# C array memory layout | ||
_default_order = 'C' | ||
|
||
|
||
class DeprecatedCArrayProxy(ArrayProxy): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Timed out depraction again (as above)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is specifically for testing. The warning/expiration will show up in
effigies marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# Used in test_deprecated_order_classvar. Remove when that test is removed (8.0) | ||
order = 'C' | ||
|
||
|
||
|
@@ -81,6 +89,9 @@ def test_init(): | |
assert ap.shape != shape | ||
# Data stays the same, also | ||
assert_array_equal(np.asarray(ap), arr) | ||
# You wouldn't do this, but order=None explicitly requests the default order | ||
ap2 = ArrayProxy(bio, FunkyHeader(arr.shape), order=None) | ||
assert_array_equal(np.asarray(ap2), arr) | ||
# C order also possible | ||
bio = BytesIO() | ||
bio.seek(16) | ||
|
@@ -90,6 +101,8 @@ def test_init(): | |
# Illegal init | ||
with pytest.raises(TypeError): | ||
ArrayProxy(bio, object()) | ||
with pytest.raises(ValueError): | ||
ArrayProxy(bio, hdr, order='badval') | ||
|
||
|
||
def test_tuplespec(): | ||
|
@@ -154,33 +167,87 @@ def test_nifti1_init(): | |
assert_array_equal(np.asarray(ap), arr * 2.0 + 10) | ||
|
||
|
||
def test_proxy_slicing(): | ||
shapes = (15, 16, 17) | ||
for n_dim in range(1, len(shapes) + 1): | ||
shape = shapes[:n_dim] | ||
arr = np.arange(np.prod(shape)).reshape(shape) | ||
for offset in (0, 20): | ||
hdr = Nifti1Header() | ||
hdr.set_data_offset(offset) | ||
hdr.set_data_dtype(arr.dtype) | ||
hdr.set_data_shape(shape) | ||
for order, klass in ('F', ArrayProxy), ('C', CArrayProxy): | ||
fobj = BytesIO() | ||
fobj.write(b'\0' * offset) | ||
fobj.write(arr.tobytes(order=order)) | ||
prox = klass(fobj, hdr) | ||
for sliceobj in slicer_samples(shape): | ||
assert_array_equal(arr[sliceobj], prox[sliceobj]) | ||
# Check slicing works with scaling | ||
@pytest.mark.parametrize("n_dim", (1, 2, 3)) | ||
@pytest.mark.parametrize("offset", (0, 20)) | ||
def test_proxy_slicing(n_dim, offset): | ||
shape = (15, 16, 17)[:n_dim] | ||
arr = np.arange(np.prod(shape)).reshape(shape) | ||
hdr = Nifti1Header() | ||
hdr.set_data_offset(offset) | ||
hdr.set_data_dtype(arr.dtype) | ||
hdr.set_data_shape(shape) | ||
for order, klass in ('F', ArrayProxy), ('C', CArrayProxy): | ||
fobj = BytesIO() | ||
fobj.write(b'\0' * offset) | ||
fobj.write(arr.tobytes(order=order)) | ||
prox = klass(fobj, hdr) | ||
assert prox.order == order | ||
for sliceobj in slicer_samples(shape): | ||
assert_array_equal(arr[sliceobj], prox[sliceobj]) | ||
|
||
|
||
def test_proxy_slicing_with_scaling(): | ||
shape = (15, 16, 17) | ||
offset = 20 | ||
arr = np.arange(np.prod(shape)).reshape(shape) | ||
hdr = Nifti1Header() | ||
hdr.set_data_offset(offset) | ||
hdr.set_data_dtype(arr.dtype) | ||
hdr.set_data_shape(shape) | ||
hdr.set_slope_inter(2.0, 1.0) | ||
fobj = BytesIO() | ||
fobj.write(b'\0' * offset) | ||
fobj.write(bytes(offset)) | ||
fobj.write(arr.tobytes(order='F')) | ||
prox = ArrayProxy(fobj, hdr) | ||
sliceobj = (None, slice(None), 1, -1) | ||
assert_array_equal(arr[sliceobj] * 2.0 + 1.0, prox[sliceobj]) | ||
|
||
|
||
@pytest.mark.parametrize("order", ("C", "F")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also test There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does not work for |
||
def test_order_override(order): | ||
shape = (15, 16, 17) | ||
arr = np.arange(np.prod(shape)).reshape(shape) | ||
fobj = BytesIO() | ||
fobj.write(arr.tobytes(order=order)) | ||
for klass in (ArrayProxy, CArrayProxy): | ||
prox = klass(fobj, (shape, arr.dtype), order=order) | ||
assert prox.order == order | ||
sliceobj = (None, slice(None), 1, -1) | ||
assert_array_equal(arr[sliceobj], prox[sliceobj]) | ||
|
||
|
||
def test_deprecated_order_classvar(): | ||
shape = (15, 16, 17) | ||
arr = np.arange(np.prod(shape)).reshape(shape) | ||
fobj = BytesIO() | ||
fobj.write(arr.tobytes(order='C')) | ||
sliceobj = (None, slice(None), 1, -1) | ||
|
||
# We don't really care about the original order, just that the behavior | ||
# of the deprecated mode matches the new behavior | ||
fprox = ArrayProxy(fobj, (shape, arr.dtype), order='F') | ||
cprox = ArrayProxy(fobj, (shape, arr.dtype), order='C') | ||
|
||
# Start raising errors when we crank the dev version | ||
if Version(__version__) >= Version('7.0.0.dev0'): | ||
cm = pytest.raises(ExpiredDeprecationError) | ||
else: | ||
cm = pytest.deprecated_call() | ||
Comment on lines
+231
to
+235
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... here. |
||
|
||
with cm: | ||
prox = DeprecatedCArrayProxy(fobj, (shape, arr.dtype)) | ||
assert prox.order == 'C' | ||
assert_array_equal(prox[sliceobj], cprox[sliceobj]) | ||
with cm: | ||
prox = DeprecatedCArrayProxy(fobj, (shape, arr.dtype), order='C') | ||
assert prox.order == 'C' | ||
assert_array_equal(prox[sliceobj], cprox[sliceobj]) | ||
with cm: | ||
prox = DeprecatedCArrayProxy(fobj, (shape, arr.dtype), order='F') | ||
assert prox.order == 'F' | ||
assert_array_equal(prox[sliceobj], fprox[sliceobj]) | ||
|
||
|
||
def test_is_proxy(): | ||
# Test is_proxy function | ||
hdr = FunkyHeader((2, 3, 4)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forget the mechanism to time out the deprecation warning ... but shouldn't we put that in here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a decorator that works for deprecating an entire function/method/class. It does not work for cases like this. This is why I added the check below: