1515
1616import pickle
1717from io import BytesIO
18+ from packaging .version import Version
1819from ..tmpdirs import InTemporaryDirectory
1920
2021import numpy as np
2122
23+ from .. import __version__
2224from ..arrayproxy import (ArrayProxy , is_proxy , reshape_dataobj , get_obj_dtype )
2325from ..openers import ImageOpener
2426from ..nifti1 import Nifti1Header
27+ from ..deprecator import ExpiredDeprecationError
2528
2629from unittest import mock
2730
@@ -57,6 +60,11 @@ def copy(self):
5760
5861class CArrayProxy (ArrayProxy ):
5962 # C array memory layout
63+ _default_order = 'C'
64+
65+
66+ class DeprecatedCArrayProxy (ArrayProxy ):
67+ # Used in test_deprecated_order_classvar. Remove when that test is removed (8.0)
6068 order = 'C'
6169
6270
@@ -81,6 +89,9 @@ def test_init():
8189 assert ap .shape != shape
8290 # Data stays the same, also
8391 assert_array_equal (np .asarray (ap ), arr )
92+ # You wouldn't do this, but order=None explicitly requests the default order
93+ ap2 = ArrayProxy (bio , FunkyHeader (arr .shape ), order = None )
94+ assert_array_equal (np .asarray (ap2 ), arr )
8495 # C order also possible
8596 bio = BytesIO ()
8697 bio .seek (16 )
@@ -90,6 +101,8 @@ def test_init():
90101 # Illegal init
91102 with pytest .raises (TypeError ):
92103 ArrayProxy (bio , object ())
104+ with pytest .raises (ValueError ):
105+ ArrayProxy (bio , hdr , order = 'badval' )
93106
94107
95108def test_tuplespec ():
@@ -154,33 +167,87 @@ def test_nifti1_init():
154167 assert_array_equal (np .asarray (ap ), arr * 2.0 + 10 )
155168
156169
157- def test_proxy_slicing ():
158- shapes = (15 , 16 , 17 )
159- for n_dim in range (1 , len (shapes ) + 1 ):
160- shape = shapes [:n_dim ]
161- arr = np .arange (np .prod (shape )).reshape (shape )
162- for offset in (0 , 20 ):
163- hdr = Nifti1Header ()
164- hdr .set_data_offset (offset )
165- hdr .set_data_dtype (arr .dtype )
166- hdr .set_data_shape (shape )
167- for order , klass in ('F' , ArrayProxy ), ('C' , CArrayProxy ):
168- fobj = BytesIO ()
169- fobj .write (b'\0 ' * offset )
170- fobj .write (arr .tobytes (order = order ))
171- prox = klass (fobj , hdr )
172- for sliceobj in slicer_samples (shape ):
173- assert_array_equal (arr [sliceobj ], prox [sliceobj ])
174- # Check slicing works with scaling
170+ @pytest .mark .parametrize ("n_dim" , (1 , 2 , 3 ))
171+ @pytest .mark .parametrize ("offset" , (0 , 20 ))
172+ def test_proxy_slicing (n_dim , offset ):
173+ shape = (15 , 16 , 17 )[:n_dim ]
174+ arr = np .arange (np .prod (shape )).reshape (shape )
175+ hdr = Nifti1Header ()
176+ hdr .set_data_offset (offset )
177+ hdr .set_data_dtype (arr .dtype )
178+ hdr .set_data_shape (shape )
179+ for order , klass in ('F' , ArrayProxy ), ('C' , CArrayProxy ):
180+ fobj = BytesIO ()
181+ fobj .write (b'\0 ' * offset )
182+ fobj .write (arr .tobytes (order = order ))
183+ prox = klass (fobj , hdr )
184+ assert prox .order == order
185+ for sliceobj in slicer_samples (shape ):
186+ assert_array_equal (arr [sliceobj ], prox [sliceobj ])
187+
188+
189+ def test_proxy_slicing_with_scaling ():
190+ shape = (15 , 16 , 17 )
191+ offset = 20
192+ arr = np .arange (np .prod (shape )).reshape (shape )
193+ hdr = Nifti1Header ()
194+ hdr .set_data_offset (offset )
195+ hdr .set_data_dtype (arr .dtype )
196+ hdr .set_data_shape (shape )
175197 hdr .set_slope_inter (2.0 , 1.0 )
176198 fobj = BytesIO ()
177- fobj .write (b' \0 ' * offset )
199+ fobj .write (bytes ( offset ) )
178200 fobj .write (arr .tobytes (order = 'F' ))
179201 prox = ArrayProxy (fobj , hdr )
180202 sliceobj = (None , slice (None ), 1 , - 1 )
181203 assert_array_equal (arr [sliceobj ] * 2.0 + 1.0 , prox [sliceobj ])
182204
183205
206+ @pytest .mark .parametrize ("order" , ("C" , "F" ))
207+ def test_order_override (order ):
208+ shape = (15 , 16 , 17 )
209+ arr = np .arange (np .prod (shape )).reshape (shape )
210+ fobj = BytesIO ()
211+ fobj .write (arr .tobytes (order = order ))
212+ for klass in (ArrayProxy , CArrayProxy ):
213+ prox = klass (fobj , (shape , arr .dtype ), order = order )
214+ assert prox .order == order
215+ sliceobj = (None , slice (None ), 1 , - 1 )
216+ assert_array_equal (arr [sliceobj ], prox [sliceobj ])
217+
218+
219+ def test_deprecated_order_classvar ():
220+ shape = (15 , 16 , 17 )
221+ arr = np .arange (np .prod (shape )).reshape (shape )
222+ fobj = BytesIO ()
223+ fobj .write (arr .tobytes (order = 'C' ))
224+ sliceobj = (None , slice (None ), 1 , - 1 )
225+
226+ # We don't really care about the original order, just that the behavior
227+ # of the deprecated mode matches the new behavior
228+ fprox = ArrayProxy (fobj , (shape , arr .dtype ), order = 'F' )
229+ cprox = ArrayProxy (fobj , (shape , arr .dtype ), order = 'C' )
230+
231+ # Start raising errors when we crank the dev version
232+ if Version (__version__ ) >= Version ('7.0.0.dev0' ):
233+ cm = pytest .raises (ExpiredDeprecationError )
234+ else :
235+ cm = pytest .deprecated_call ()
236+
237+ with cm :
238+ prox = DeprecatedCArrayProxy (fobj , (shape , arr .dtype ))
239+ assert prox .order == 'C'
240+ assert_array_equal (prox [sliceobj ], cprox [sliceobj ])
241+ with cm :
242+ prox = DeprecatedCArrayProxy (fobj , (shape , arr .dtype ), order = 'C' )
243+ assert prox .order == 'C'
244+ assert_array_equal (prox [sliceobj ], cprox [sliceobj ])
245+ with cm :
246+ prox = DeprecatedCArrayProxy (fobj , (shape , arr .dtype ), order = 'F' )
247+ assert prox .order == 'F'
248+ assert_array_equal (prox [sliceobj ], fprox [sliceobj ])
249+
250+
184251def test_is_proxy ():
185252 # Test is_proxy function
186253 hdr = FunkyHeader ((2 , 3 , 4 ))
0 commit comments