@@ -195,156 +195,20 @@ class DataInterfaceMixin(GetSetDtypeMixin):
195195 Use this mixin if your image has a ``dataobj`` property that contains an
196196 array or an array-like thing.
197197 """
198+ meth_names = ('get_fdata' , 'get_data' )
199+
198200 def validate_data_interface (self , imaker , params ):
199201 # Check get data returns array, and caches
200202 img = imaker ()
201203 assert_equal (img .shape , img .dataobj .shape )
202204 assert_data_similar (img .dataobj , params )
203- meth_names = ('get_fdata' , 'get_data' )
204- for meth_name in meth_names :
205+ for meth_name in self .meth_names :
205206 if params ['is_proxy' ]:
206- # Parameters assert this is an array proxy
207- img = imaker ()
208- # Does is_proxy agree?
209- assert_true (is_proxy (img .dataobj ))
210- # Confirm it is not a numpy array
211- assert_false (isinstance (img .dataobj , np .ndarray ))
212- # Confirm it can be converted to a numpy array with asarray
213- proxy_data = np .asarray (img .dataobj )
214- proxy_copy = proxy_data .copy ()
215- # Not yet cached, proxy image: in_memory is False
216- assert_false (img .in_memory )
217- # Load with caching='unchanged'
218- method = getattr (img , meth_name )
219- data = method (caching = 'unchanged' )
220- # Still not cached
221- assert_false (img .in_memory )
222- # Default load, does caching
223- data = method ()
224- # Data now cached. in_memory is True if either of the get_data
225- # or get_fdata caches are not-None
226- assert_true (img .in_memory )
227- # We previously got proxy_data from disk, but data, which we
228- # have just fetched, is a fresh copy.
229- assert_false (proxy_data is data )
230- # asarray on dataobj, applied above, returns same numerical
231- # values. This might not be true get_fdata operating on huge
232- # integers, but lets assume that's not true here.
233- assert_array_equal (proxy_data , data )
234- # Now caching='unchanged' does nothing, returns cached version
235- data_again = method (caching = 'unchanged' )
236- assert_true (data is data_again )
237- # caching='fill' does nothing because the cache is already full
238- data_yet_again = method (caching = 'fill' )
239- assert_true (data is data_yet_again )
240- # changing array data does not change proxy data, or reloaded
241- # data
242- data [:] = 42
243- assert_array_equal (proxy_data , proxy_copy )
244- assert_array_equal (np .asarray (img .dataobj ), proxy_copy )
245- # It does change the result of get_data
246- assert_array_equal (method (), 42 )
247- # until we uncache
248- img .uncache ()
249- # Which unsets in_memory
250- assert_false (img .in_memory )
251- assert_array_equal (method (), proxy_copy )
252- # Check caching='fill' does cache data
253- img = imaker ()
254- method = getattr (img , meth_name )
255- assert_false (img .in_memory )
256- data = method (caching = 'fill' )
257- assert_true (img .in_memory )
258- data_again = method ()
259- assert_true (data is data_again )
260- # Check the interaction of caching with get_data, get_fdata.
261- # Caching for `get_data` should have no effect on caching for
262- # get_fdata, and vice versa.
263- # Modify the cached data
264- data [:] = 43
265- # Load using the other data fetch method
266- other_name = set (meth_names ).difference ({meth_name }).pop ()
267- other_method = getattr (img , other_name )
268- other_data = other_method ()
269- # We get the original data, not the modified cache
270- assert_array_equal (proxy_data , other_data )
271- assert_false (np .all (data == other_data ))
272- # We can modify the other cache, without affecting the first
273- other_data [:] = 44
274- assert_array_equal (other_method (), 44 )
275- assert_false (np .all (method () == other_method ()))
276- # Check that caching refreshes for new floating point type.
277- if meth_name == 'get_fdata' :
278- img .uncache ()
279- fdata = img .get_fdata ()
280- assert_equal (fdata .dtype , np .float64 )
281- fdata [:] = 42
282- fdata_back = img .get_fdata ()
283- assert_array_equal (fdata_back , 42 )
284- assert_equal (fdata_back .dtype , np .float64 )
285- # New data dtype, no caching, doesn't use or alter cache
286- fdata_new_dt = img .get_fdata (caching = 'unchanged' , dtype = 'f4' )
287- # We get back the original read, not the modified cache
288- assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
289- assert_equal (fdata_new_dt .dtype , np .float32 )
290- # The original cache stays in place, for default float64
291- assert_array_equal (img .get_fdata (), 42 )
292- # And for not-default float32, because we haven't cached
293- fdata_new_dt [:] = 43
294- fdata_new_dt = img .get_fdata (caching = 'unchanged' , dtype = 'f4' )
295- assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
296- # Until we reset with caching='fill', at which point we
297- # drop the original float64 cache, and have a float32 cache
298- fdata_new_dt = img .get_fdata (caching = 'fill' , dtype = 'f4' )
299- assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
300- # We're using the cache, for dtype='f4' reads
301- fdata_new_dt [:] = 43
302- assert_array_equal (img .get_fdata (dtype = 'f4' ), 43 )
303- # We've lost the cache for float64 reads (no longer 42)
304- assert_array_equal (img .get_fdata (), proxy_data )
305- else : # not proxy
306- for caching in (None , 'fill' , 'unchanged' ):
307- img = imaker ()
308- method = getattr (img , meth_name )
309- get_data_func = (method if caching is None else
310- partial (method , caching = caching ))
311- assert_true (isinstance (img .dataobj , np .ndarray ))
312- assert_true (img .in_memory )
313- data = get_data_func ()
314- # Returned data same object as underlying dataobj if using
315- # old ``get_data`` method, or using newer ``get_fdata``
316- # method, where original array was float64.
317- dataobj_is_data = (img .dataobj .dtype == np .float64
318- or method == img .get_data )
319- # Set something to the output array.
320- data [:] = 42
321- get_result_changed = np .all (get_data_func () == 42 )
322- assert_equal (get_result_changed ,
323- dataobj_is_data or caching != 'unchanged' )
324- if dataobj_is_data :
325- assert_true (data is img .dataobj )
326- # Changing array data changes
327- # data
328- assert_array_equal (np .asarray (img .dataobj ), 42 )
329- # Uncache has no effect
330- img .uncache ()
331- assert_array_equal (get_data_func (), 42 )
332- else :
333- assert_false (data is img .dataobj )
334- assert_false (np .all (np .asarray (img .dataobj ) == 42 ))
335- # Uncache does have an effect
336- img .uncache ()
337- assert_false (np .all (get_data_func () == 42 ))
338- # in_memory is always true for array images, regardless of
339- # cache state.
340- img .uncache ()
341- assert_true (img .in_memory )
342- # Values to get_(f)data caching parameter must be 'fill' or
343- # 'unchanged'
344- assert_raises (ValueError , img .get_data , caching = 'something' )
345- assert_raises (ValueError , img .get_fdata , caching = 'something' )
207+ self ._check_proxy_interface (imaker , meth_name )
208+ else : # Array image
209+ self ._check_array_interface (imaker , meth_name )
346210 # Data shape is same as image shape
347- assert_equal (img .shape , method ().shape )
211+ assert_equal (img .shape , getattr ( img , meth_name ) ().shape )
348212 # Values to get_data caching parameter must be 'fill' or
349213 # 'unchanged'
350214 assert_raises (ValueError , img .get_data , caching = 'something' )
@@ -354,6 +218,155 @@ def validate_data_interface(self, imaker, params):
354218 # So is in_memory
355219 assert_raises (AttributeError , setattr , img , 'in_memory' , False )
356220
221+ def _check_proxy_interface (self , imaker , meth_name ):
222+ # Parameters assert this is an array proxy
223+ img = imaker ()
224+ # Does is_proxy agree?
225+ assert_true (is_proxy (img .dataobj ))
226+ # Confirm it is not a numpy array
227+ assert_false (isinstance (img .dataobj , np .ndarray ))
228+ # Confirm it can be converted to a numpy array with asarray
229+ proxy_data = np .asarray (img .dataobj )
230+ proxy_copy = proxy_data .copy ()
231+ # Not yet cached, proxy image: in_memory is False
232+ assert_false (img .in_memory )
233+ # Load with caching='unchanged'
234+ method = getattr (img , meth_name )
235+ data = method (caching = 'unchanged' )
236+ # Still not cached
237+ assert_false (img .in_memory )
238+ # Default load, does caching
239+ data = method ()
240+ # Data now cached. in_memory is True if either of the get_data
241+ # or get_fdata caches are not-None
242+ assert_true (img .in_memory )
243+ # We previously got proxy_data from disk, but data, which we
244+ # have just fetched, is a fresh copy.
245+ assert_false (proxy_data is data )
246+ # asarray on dataobj, applied above, returns same numerical
247+ # values. This might not be true get_fdata operating on huge
248+ # integers, but lets assume that's not true here.
249+ assert_array_equal (proxy_data , data )
250+ # Now caching='unchanged' does nothing, returns cached version
251+ data_again = method (caching = 'unchanged' )
252+ assert_true (data is data_again )
253+ # caching='fill' does nothing because the cache is already full
254+ data_yet_again = method (caching = 'fill' )
255+ assert_true (data is data_yet_again )
256+ # changing array data does not change proxy data, or reloaded
257+ # data
258+ data [:] = 42
259+ assert_array_equal (proxy_data , proxy_copy )
260+ assert_array_equal (np .asarray (img .dataobj ), proxy_copy )
261+ # It does change the result of get_data
262+ assert_array_equal (method (), 42 )
263+ # until we uncache
264+ img .uncache ()
265+ # Which unsets in_memory
266+ assert_false (img .in_memory )
267+ assert_array_equal (method (), proxy_copy )
268+ # Check caching='fill' does cache data
269+ img = imaker ()
270+ method = getattr (img , meth_name )
271+ assert_false (img .in_memory )
272+ data = method (caching = 'fill' )
273+ assert_true (img .in_memory )
274+ data_again = method ()
275+ assert_true (data is data_again )
276+ # Check the interaction of caching with get_data, get_fdata.
277+ # Caching for `get_data` should have no effect on caching for
278+ # get_fdata, and vice versa.
279+ # Modify the cached data
280+ data [:] = 43
281+ # Load using the other data fetch method
282+ other_name = set (self .meth_names ).difference ({meth_name }).pop ()
283+ other_method = getattr (img , other_name )
284+ other_data = other_method ()
285+ # We get the original data, not the modified cache
286+ assert_array_equal (proxy_data , other_data )
287+ assert_false (np .all (data == other_data ))
288+ # We can modify the other cache, without affecting the first
289+ other_data [:] = 44
290+ assert_array_equal (other_method (), 44 )
291+ assert_false (np .all (method () == other_method ()))
292+ if meth_name != 'get_fdata' :
293+ return
294+ # Check that caching refreshes for new floating point type.
295+ img .uncache ()
296+ fdata = img .get_fdata ()
297+ assert_equal (fdata .dtype , np .float64 )
298+ fdata [:] = 42
299+ fdata_back = img .get_fdata ()
300+ assert_array_equal (fdata_back , 42 )
301+ assert_equal (fdata_back .dtype , np .float64 )
302+ # New data dtype, no caching, doesn't use or alter cache
303+ fdata_new_dt = img .get_fdata (caching = 'unchanged' , dtype = 'f4' )
304+ # We get back the original read, not the modified cache
305+ assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
306+ assert_equal (fdata_new_dt .dtype , np .float32 )
307+ # The original cache stays in place, for default float64
308+ assert_array_equal (img .get_fdata (), 42 )
309+ # And for not-default float32, because we haven't cached
310+ fdata_new_dt [:] = 43
311+ fdata_new_dt = img .get_fdata (caching = 'unchanged' , dtype = 'f4' )
312+ assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
313+ # Until we reset with caching='fill', at which point we
314+ # drop the original float64 cache, and have a float32 cache
315+ fdata_new_dt = img .get_fdata (caching = 'fill' , dtype = 'f4' )
316+ assert_array_equal (fdata_new_dt , proxy_data .astype ('f4' ))
317+ # We're using the cache, for dtype='f4' reads
318+ fdata_new_dt [:] = 43
319+ assert_array_equal (img .get_fdata (dtype = 'f4' ), 43 )
320+ # We've lost the cache for float64 reads (no longer 42)
321+ assert_array_equal (img .get_fdata (), proxy_data )
322+
323+ def _check_array_interface (self , imaker , meth_name ):
324+ for caching in (None , 'fill' , 'unchanged' ):
325+ self ._check_array_caching (imaker , meth_name , caching )
326+ # Values to get_(f)data caching parameter must be 'fill' or
327+ # 'unchanged'
328+ img = imaker ()
329+ for meth_name in self .meth_names :
330+ method = getattr (img , meth_name )
331+ assert_raises (ValueError , method , caching = 'something' )
332+
333+ def _check_array_caching (self , imaker , meth_name , caching ):
334+ img = imaker ()
335+ method = getattr (img , meth_name )
336+ get_data_func = (method if caching is None else
337+ partial (method , caching = caching ))
338+ assert_true (isinstance (img .dataobj , np .ndarray ))
339+ assert_true (img .in_memory )
340+ data = get_data_func ()
341+ # Returned data same object as underlying dataobj if using
342+ # old ``get_data`` method, or using newer ``get_fdata``
343+ # method, where original array was float64.
344+ dataobj_is_data = (img .dataobj .dtype == np .float64
345+ or method == img .get_data )
346+ # Set something to the output array.
347+ data [:] = 42
348+ get_result_changed = np .all (get_data_func () == 42 )
349+ assert_equal (get_result_changed ,
350+ dataobj_is_data or caching != 'unchanged' )
351+ if dataobj_is_data :
352+ assert_true (data is img .dataobj )
353+ # Changing array data changes
354+ # data
355+ assert_array_equal (np .asarray (img .dataobj ), 42 )
356+ # Uncache has no effect
357+ img .uncache ()
358+ assert_array_equal (get_data_func (), 42 )
359+ else :
360+ assert_false (data is img .dataobj )
361+ assert_false (np .all (np .asarray (img .dataobj ) == 42 ))
362+ # Uncache does have an effect
363+ img .uncache ()
364+ assert_false (np .all (get_data_func () == 42 ))
365+ # in_memory is always true for array images, regardless of
366+ # cache state.
367+ img .uncache ()
368+ assert_true (img .in_memory )
369+
357370 def validate_data_deprecated (self , imaker , params ):
358371 # Check _data property still exists, but raises warning
359372 img = imaker ()
@@ -385,7 +398,6 @@ def validate_shape_deprecated(self, imaker, params):
385398 assert_equal (len (w ), 1 )
386399
387400
388-
389401class HeaderShapeMixin (object ):
390402 """ Tests that header shape can be set and got
391403
0 commit comments