47
47
from ..tmpdirs import InTemporaryDirectory
48
48
49
49
from .test_api_validators import ValidateAPI
50
- from .test_helpers import bytesio_round_trip , assert_data_similar
50
+ from .test_helpers import (bytesio_round_trip , bytesio_filemap ,
51
+ assert_data_similar )
51
52
from .test_minc1 import EXAMPLE_IMAGES as MINC1_EXAMPLE_IMAGES
52
53
from .test_minc2 import EXAMPLE_IMAGES as MINC2_EXAMPLE_IMAGES
53
54
from .test_parrec import EXAMPLE_IMAGES as PARREC_EXAMPLE_IMAGES
@@ -100,38 +101,10 @@ def obj_params(self):
100
101
"""
101
102
raise NotImplementedError
102
103
103
- def validate_affine (self , imaker , params ):
104
- # Check affine API
105
- img = imaker ()
106
- assert_almost_equal (img .affine , params ['affine' ], 6 )
107
- assert_equal (img .affine .dtype , np .float64 )
108
- img .affine [0 , 0 ] = 1.5
109
- assert_equal (img .affine [0 , 0 ], 1.5 )
110
- # Read only
111
- assert_raises (AttributeError , setattr , img , 'affine' , np .eye (4 ))
112
-
113
- def validate_affine_deprecated (self , imaker , params ):
114
- # Check deprecated affine API
115
- img = imaker ()
116
- with clear_and_catch_warnings () as w :
117
- warnings .simplefilter ('always' , DeprecationWarning )
118
- assert_almost_equal (img .get_affine (), params ['affine' ], 6 )
119
- assert_equal (len (w ), 1 )
120
- assert_equal (img .get_affine ().dtype , np .float64 )
121
- aff = img .get_affine ()
122
- aff [0 , 0 ] = 1.5
123
- assert_true (aff is img .get_affine ())
124
-
125
104
def validate_header (self , imaker , params ):
126
105
# Check header API
127
106
img = imaker ()
128
107
hdr = img .header # we can fetch it
129
- # Change shape in header, check this changes img.header
130
- shape = hdr .get_data_shape ()
131
- new_shape = (shape [0 ] + 1 ,) + shape [1 :]
132
- hdr .set_data_shape (new_shape )
133
- assert_true (img .header is hdr )
134
- assert_equal (img .header .get_data_shape (), new_shape )
135
108
# Read only
136
109
assert_raises (AttributeError , setattr , img , 'header' , hdr )
137
110
@@ -152,7 +125,6 @@ def validate_shape(self, imaker, params):
152
125
# Same as array shape if passed
153
126
if 'data' in params :
154
127
assert_equal (img .shape , params ['data' ].shape )
155
- assert_equal (img .shape , img .get_data ().shape )
156
128
# Read only
157
129
assert_raises (AttributeError , setattr , img , 'shape' , np .eye (4 ))
158
130
@@ -164,6 +136,51 @@ def validate_shape_deprecated(self, imaker, params):
164
136
assert_equal (img .get_shape (), params ['shape' ])
165
137
assert_equal (len (w ), 1 )
166
138
139
+ def validate_filenames (self , imaker , params ):
140
+ # Validate the filename, file_map interface
141
+ if not self .can_save :
142
+ raise SkipTest
143
+ img = imaker ()
144
+ img .set_data_dtype (np .float32 ) # to avoid rounding in load / save
145
+ # Make sure the object does not have a file_map
146
+ img .file_map = None
147
+ # The bytesio_round_trip helper tests bytesio load / save via file_map
148
+ rt_img = bytesio_round_trip (img )
149
+ assert_array_equal (img .shape , rt_img .shape )
150
+ assert_almost_equal (img .get_data (), rt_img .get_data ())
151
+ # Give the image a file map
152
+ klass = type (img )
153
+ rt_img .file_map = bytesio_filemap (klass )
154
+ # This object can now be saved and loaded from its own file_map
155
+ rt_img .to_file_map ()
156
+ rt_rt_img = klass .from_file_map (rt_img .file_map )
157
+ assert_almost_equal (img .get_data (), rt_rt_img .get_data ())
158
+ # get_ / set_ filename
159
+ fname = 'an_image' + self .standard_extension
160
+ img .set_filename (fname )
161
+ assert_equal (img .get_filename (), fname )
162
+ assert_equal (img .file_map ['image' ].filename , fname )
163
+ # to_ / from_ filename
164
+ fname = 'another_image' + self .standard_extension
165
+ with InTemporaryDirectory ():
166
+ img .to_filename (fname )
167
+ rt_img = img .__class__ .from_filename (fname )
168
+ assert_array_equal (img .shape , rt_img .shape )
169
+ assert_almost_equal (img .get_data (), rt_img .get_data ())
170
+ del rt_img # to allow windows to delete the directory
171
+
172
+ def validate_no_slicing (self , imaker , params ):
173
+ img = imaker ()
174
+ assert_raises (TypeError , img .__getitem__ , 'string' )
175
+ assert_raises (TypeError , img .__getitem__ , slice (None ))
176
+
177
+
178
+ class GetSetDtypeMixin (object ):
179
+ """ Adds dtype tests
180
+
181
+ Add this one if your image has ``get_data_dtype`` and ``set_data_dtype``.
182
+ """
183
+
167
184
def validate_dtype (self , imaker , params ):
168
185
# data / storage dtype
169
186
img = imaker ()
@@ -182,9 +199,17 @@ def validate_dtype(self, imaker, params):
182
199
rt_img = bytesio_round_trip (img )
183
200
assert_equal (rt_img .get_data_dtype ().type , np .float32 )
184
201
185
- def validate_data (self , imaker , params ):
202
+
203
+ class DataInterfaceMixin (GetSetDtypeMixin ):
204
+ """ Test dataobj interface for images with array backing
205
+
206
+ Use this mixin if your image has a ``dataobj`` property that contains an
207
+ array or an array-like thing.
208
+ """
209
+ def validate_data_interface (self , imaker , params ):
186
210
# Check get data returns array, and caches
187
211
img = imaker ()
212
+ assert_equal (img .shape , img .dataobj .shape )
188
213
assert_data_similar (img .dataobj , params )
189
214
if params ['is_proxy' ]:
190
215
assert_false (isinstance (img .dataobj , np .ndarray ))
@@ -243,6 +268,8 @@ def validate_data(self, imaker, params):
243
268
img .uncache ()
244
269
assert_array_equal (get_data_func (), 42 )
245
270
assert_true (img .in_memory )
271
+ # Data shape is same as image shape
272
+ assert_equal (img .shape , img .get_data ().shape )
246
273
# dataobj is read only
247
274
fake_data = np .zeros (img .shape ).astype (img .get_data_dtype ())
248
275
assert_raises (AttributeError , setattr , img , 'dataobj' , fake_data )
@@ -262,37 +289,60 @@ def validate_data_deprecated(self, imaker, params):
262
289
fake_data = np .zeros (img .shape ).astype (img .get_data_dtype ())
263
290
assert_raises (AttributeError , setattr , img , '_data' , fake_data )
264
291
265
- def validate_filenames (self , imaker , params ):
266
- # Validate the filename, file_map interface
267
- if not self .can_save :
268
- raise SkipTest
292
+
293
+ class HeaderShapeMixin (object ):
294
+ """ Tests that header shape can be set and got
295
+
296
+ Add this one of your header supports ``get_data_shape`` and
297
+ ``set_data_shape``.
298
+ """
299
+
300
+ def validate_header_shape (self , imaker , params ):
301
+ # Change shape in header, check this changes img.header
269
302
img = imaker ()
270
- img .set_data_dtype (np .float32 ) # to avoid rounding in load / save
271
- # The bytesio_round_trip helper tests bytesio load / save via file_map
272
- rt_img = bytesio_round_trip (img )
273
- assert_array_equal (img .shape , rt_img .shape )
274
- assert_almost_equal (img .get_data (), rt_img .get_data ())
275
- # get_ / set_ filename
276
- fname = 'an_image' + self .standard_extension
277
- img .set_filename (fname )
278
- assert_equal (img .get_filename (), fname )
279
- assert_equal (img .file_map ['image' ].filename , fname )
280
- # to_ / from_ filename
281
- fname = 'another_image' + self .standard_extension
282
- with InTemporaryDirectory ():
283
- img .to_filename (fname )
284
- rt_img = img .__class__ .from_filename (fname )
285
- assert_array_equal (img .shape , rt_img .shape )
286
- assert_almost_equal (img .get_data (), rt_img .get_data ())
287
- del rt_img # to allow windows to delete the directory
303
+ hdr = img .header
304
+ shape = hdr .get_data_shape ()
305
+ new_shape = (shape [0 ] + 1 ,) + shape [1 :]
306
+ hdr .set_data_shape (new_shape )
307
+ assert_true (img .header is hdr )
308
+ assert_equal (img .header .get_data_shape (), new_shape )
288
309
289
- def validate_no_slicing (self , imaker , params ):
310
+
311
+ class AffineMixin (object ):
312
+ """ Adds test of affine property, method
313
+
314
+ Add this one if your image has an ``affine`` property. If so, it should
315
+ (for now) also have a ``get_affine`` method returning the same result.
316
+ """
317
+
318
+ def validate_affine (self , imaker , params ):
319
+ # Check affine API
290
320
img = imaker ()
291
- assert_raises (TypeError , img .__getitem__ , 'string' )
292
- assert_raises (TypeError , img .__getitem__ , slice (None ))
321
+ assert_almost_equal (img .affine , params ['affine' ], 6 )
322
+ assert_equal (img .affine .dtype , np .float64 )
323
+ img .affine [0 , 0 ] = 1.5
324
+ assert_equal (img .affine [0 , 0 ], 1.5 )
325
+ # Read only
326
+ assert_raises (AttributeError , setattr , img , 'affine' , np .eye (4 ))
327
+
328
+ def validate_affine_deprecated (self , imaker , params ):
329
+ # Check deprecated affine API
330
+ img = imaker ()
331
+ with clear_and_catch_warnings () as w :
332
+ warnings .simplefilter ('always' , DeprecationWarning )
333
+ assert_almost_equal (img .get_affine (), params ['affine' ], 6 )
334
+ assert_equal (len (w ), 1 )
335
+ assert_equal (img .get_affine ().dtype , np .float64 )
336
+ aff = img .get_affine ()
337
+ aff [0 , 0 ] = 1.5
338
+ assert_true (aff is img .get_affine ())
293
339
294
340
295
- class LoadImageAPI (GenericImageAPI ):
341
+ class LoadImageAPI (GenericImageAPI ,
342
+ DataInterfaceMixin ,
343
+ AffineMixin ,
344
+ GetSetDtypeMixin ,
345
+ HeaderShapeMixin ):
296
346
# Callable returning an image from a filename
297
347
loader = None
298
348
# Sequence of dictionaries, where dictionaries have keys
@@ -324,9 +374,6 @@ class MakeImageAPI(LoadImageAPI):
324
374
# Example shapes for created images
325
375
example_shapes = ((2 ,), (2 , 3 ), (2 , 3 , 4 ), (2 , 3 , 4 , 5 ))
326
376
327
- def img_from_arr_aff (self , arr , aff , header = None ):
328
- return self .image_maker (arr , aff , header )
329
-
330
377
def obj_params (self ):
331
378
# Return any obj_params from superclass
332
379
for func , params in super (MakeImageAPI , self ).obj_params ():
0 commit comments