1818from ..mghformat import MGHHeader , MGHError , MGHImage
1919from ...tmpdirs import InTemporaryDirectory
2020from ...fileholders import FileHolder
21+ from ...spatialimages import HeaderDataError
2122from ...volumeutils import sys_is_le
23+ from ...wrapstruct import WrapStructError
2224
2325from nose .tools import assert_true , assert_false
2426
2527from numpy .testing import (assert_equal , assert_array_equal ,
2628 assert_array_almost_equal , assert_almost_equal ,
2729 assert_raises )
30+ from ...testing import assert_not_equal
2831
2932from ...testing import data_path
3033
3134from ...tests import test_spatialimages as tsi
35+ from ...tests .test_wrapstruct import _TestWrapStructBase
3236
3337MGZ_FNAME = os .path .join (data_path , 'test.mgz' )
3438
@@ -141,6 +145,21 @@ def test_write_noaffine_mgh():
141145 assert_array_almost_equal (h ['Pxyz_c' ], [0 , 0 , 0 ])
142146
143147
148+ def test_set_zooms ():
149+ mgz = load (MGZ_FNAME )
150+ h = mgz .header
151+ assert_array_almost_equal (h .get_zooms (), [1 , 1 , 1 , 2 ])
152+ h .set_zooms ([1 , 1 , 1 , 3 ])
153+ assert_array_almost_equal (h .get_zooms (), [1 , 1 , 1 , 3 ])
154+ for zooms in ((- 1 , 1 , 1 , 1 ),
155+ (1 , - 1 , 1 , 1 ),
156+ (1 , 1 , - 1 , 1 ),
157+ (1 , 1 , 1 , - 1 ),
158+ (1 , 1 , 1 , 1 , 5 )):
159+ with assert_raises (HeaderDataError ):
160+ h .set_zooms (zooms )
161+
162+
144163def bad_dtype_mgh ():
145164 ''' This function raises an MGHError exception because
146165 uint16 is not a valid MGH datatype.
@@ -318,17 +337,25 @@ def test_mghheader_default_structarr():
318337 MGHHeader .default_structarr (endianness = endianness )
319338
320339
321- def test_byteswap ():
340+ def test_deprecated_fields ():
322341 hdr = MGHHeader ()
323342
324- for endianness in BIG_CODES :
325- hdr2 = hdr .as_byteswapped (endianness )
326- assert_true (hdr2 is not hdr )
327- assert_equal (hdr2 , hdr )
343+ # mrparams is the only deprecated field at the moment
344+ assert_array_equal (hdr ['mrparams' ], 0 )
328345
329- for endianness in (None ,) + LITTLE_CODES :
330- with assert_raises (ValueError ):
331- hdr .as_byteswapped (endianness )
346+ hdr ['mrparams' ] = [1 , 2 , 3 , 4 ]
347+ assert_array_almost_equal (hdr ['mrparams' ], [1 , 2 , 3 , 4 ])
348+ assert_equal (hdr ['tr' ], 1 )
349+ assert_equal (hdr ['flip_angle' ], 2 )
350+ assert_equal (hdr ['te' ], 3 )
351+ assert_equal (hdr ['ti' ], 4 )
352+ assert_equal (hdr ['fov' ], 0 )
353+
354+ hdr ['tr' ] = 5
355+ hdr ['flip_angle' ] = 6
356+ hdr ['te' ] = 7
357+ hdr ['ti' ] = 8
358+ assert_array_almost_equal (hdr ['mrparams' ], [5 , 6 , 7 , 8 ])
332359
333360
334361class TestMGHImage (tsi .TestSpatialImage , tsi .MmapImageMixin ):
@@ -342,3 +369,104 @@ def check_dtypes(self, expected, actual):
342369 # others may only require the same type
343370 # MGH requires the actual to be a big endian version of expected
344371 assert_equal (expected .newbyteorder ('>' ), actual )
372+
373+
374+ class TestMGHHeader (_TestWrapStructBase ):
375+ header_class = MGHHeader
376+
377+ def test_general_init (self ):
378+ hdr = self .header_class ()
379+ # binaryblock has length given by header data dtype
380+ binblock = hdr .binaryblock
381+ assert_equal (len (binblock ), hdr .structarr .dtype .itemsize )
382+ # Endianness will always be big, and cannot be set
383+ assert_equal (hdr .endianness , '>' )
384+ # You can also pass in a check flag, without data this has no
385+ # effect
386+ hdr = self .header_class (check = False )
387+
388+ def _set_something_into_hdr (self , hdr ):
389+ hdr ['dims' ] = [4 , 3 , 2 , 1 ]
390+
391+ # Update tests to account for big-endian requirement
392+ def test__eq__ (self ):
393+ # Test equal and not equal
394+ hdr1 = self .header_class ()
395+ hdr2 = self .header_class ()
396+ assert_equal (hdr1 , hdr2 )
397+ self ._set_something_into_hdr (hdr1 )
398+ assert_not_equal (hdr1 , hdr2 )
399+ self ._set_something_into_hdr (hdr2 )
400+ assert_equal (hdr1 , hdr2 )
401+ # REMOVED as_byteswapped() test
402+ # Check comparing to funny thing says no
403+ assert_not_equal (hdr1 , None )
404+ assert_not_equal (hdr1 , 1 )
405+
406+ def test_to_from_fileobj (self ):
407+ # Successful write using write_to
408+ hdr = self .header_class ()
409+ str_io = io .BytesIO ()
410+ hdr .write_to (str_io )
411+ str_io .seek (0 )
412+ hdr2 = self .header_class .from_fileobj (str_io )
413+ assert_equal (hdr2 .endianness , '>' )
414+ assert_equal (hdr2 .binaryblock , hdr .binaryblock )
415+
416+ def test_endian_guess (self ):
417+ # Check guesses of endian
418+ eh = self .header_class ()
419+ assert_equal (eh .endianness , '>' )
420+ assert_equal (self .header_class .guessed_endian (eh ), '>' )
421+
422+ def test_bytes (self ):
423+ # Test get of bytes
424+ hdr1 = self .header_class ()
425+ bb = hdr1 .binaryblock
426+ hdr2 = self .header_class (hdr1 .binaryblock )
427+ assert_equal (hdr1 , hdr2 )
428+ assert_equal (hdr1 .binaryblock , hdr2 .binaryblock )
429+ # Do a set into the header, and try again. The specifics of 'setting
430+ # something' will depend on the nature of the bytes object
431+ self ._set_something_into_hdr (hdr1 )
432+ hdr2 = self .header_class (hdr1 .binaryblock )
433+ assert_equal (hdr1 , hdr2 )
434+ assert_equal (hdr1 .binaryblock , hdr2 .binaryblock )
435+ # Short binaryblocks give errors (here set through init)
436+ # Long binaryblocks are truncated
437+ assert_raises (WrapStructError ,
438+ self .header_class ,
439+ bb [:self .header_class ._hdrdtype .itemsize - 1 ])
440+ # Checking set to true by default, and prevents nonsense being
441+ # set into the header.
442+ bb_bad = self .get_bad_bb ()
443+ if bb_bad is None :
444+ return
445+ with imageglobals .LoggingOutputSuppressor ():
446+ assert_raises (HeaderDataError , self .header_class , bb_bad )
447+ # now slips past without check
448+ _ = self .header_class (bb_bad , check = False )
449+
450+ def test_as_byteswapped (self ):
451+ # Check byte swapping
452+ hdr = self .header_class ()
453+ assert_equal (hdr .endianness , '>' )
454+ # same code just returns a copy
455+ for endianness in BIG_CODES :
456+ hdr2 = hdr .as_byteswapped (endianness )
457+ assert_false (hdr2 is hdr )
458+ assert_equal (hdr2 , hdr )
459+
460+ # Different code raises error
461+ for endianness in (None ,) + LITTLE_CODES :
462+ with assert_raises (ValueError ):
463+ hdr .as_byteswapped (endianness )
464+ # Note that contents is not rechecked on swap / copy
465+ class DC (self .header_class ):
466+ def check_fix (self , * args , ** kwargs ):
467+ raise Exception
468+
469+ # Assumes check=True default
470+ assert_raises (Exception , DC , hdr .binaryblock )
471+ hdr = DC (hdr .binaryblock , check = False )
472+ hdr2 = hdr .as_byteswapped ('>' )
0 commit comments