3232 ('dims' , '>i4' , (4 ,)), # 4; width, height, depth, nframes
3333 ('type' , '>i4' ), # 20; data type
3434 ('dof' , '>i4' ), # 24; degrees of freedom
35- ('ras_good' , '>i2' ), # 28; *_ras fields valid
36- ('voxelsize' , '>f4' , (3 ,)), # 30; zooms (X, Y, Z)
37- ('x_ras' , '>f4' , (3 , 1 )), # 42; X direction cosine column
38- ('y_ras' , '>f4' , (3 , 1 )), # 54; Y direction cosine column
39- ('z_ras' , '>f4' , (3 , 1 )), # 66; Z direction cosine column
40- ('c_ras' , '>f4' , (3 , 1 )), # 78; mm from (0, 0, 0) RAS to vol center
35+ ('goodRASFlag' , '>i2' ), # 28; Mdc, Pxyz_c fields valid
36+ ('delta' , '>f4' , (3 ,)), # 30; zooms (X, Y, Z)
37+ ('Mdc' , '>f4' , (3 , 3 )), # 42; TRANSPOSE of direction cosine matrix
38+ ('Pxyz_c' , '>f4' , (3 ,)), # 78; mm from (0, 0, 0) RAS to vol center
4139]
4240# Optional footer. Also has more stuff after this, optionally
4341footer_dtd = [
@@ -120,7 +118,7 @@ def __init__(self,
120118 super (MGHHeader , self ).__init__ (binaryblock = binaryblock ,
121119 endianness = endianness ,
122120 check = False )
123- if not self ._structarr ['ras_good ' ]:
121+ if not self ._structarr ['goodRASFlag ' ]:
124122 self ._set_affine_default ()
125123 if check :
126124 self .check_fix ()
@@ -165,13 +163,12 @@ def get_affine(self):
165163
166164 MGH format doesn't store the transform directly. Instead it's gleaned
167165 from the zooms ( delta ), direction cosines ( Mdc ), RAS centers (
168- c_ras ) and the dimensions.
166+ Pxyz_c ) and the dimensions.
169167 '''
170- affine = np .eye (4 )
171168 hdr = self ._structarr
172- MdcD = np . hstack (( hdr ['x_ras' ], hdr [ 'y_ras' ], hdr [ 'z_ras' ])) * hdr ['voxelsize ' ]
169+ MdcD = hdr ['Mdc' ]. T * hdr ['delta ' ]
173170 vol_center = MdcD .dot (hdr ['dims' ][:3 ]) / 2
174- return from_matvec (MdcD , hdr ['c_ras' ]. T - vol_center )
171+ return from_matvec (MdcD , hdr ['Pxyz_c' ] - vol_center )
175172
176173 # For compatibility with nifti (multiple affines)
177174 get_best_affine = get_affine
@@ -185,7 +182,7 @@ def get_vox2ras_tkr(self):
185182 ''' Get the vox2ras-tkr transform. See "Torig" here:
186183 https://surfer.nmr.mgh.harvard.edu/fswiki/CoordinateSystems
187184 '''
188- ds = self ._structarr ['voxelsize ' ]
185+ ds = self ._structarr ['delta ' ]
189186 ns = self ._structarr ['dims' ][:3 ] * ds / 2.0
190187 v2rtkr = np .array ([[- ds [0 ], 0 , 0 , ns [0 ]],
191188 [0 , 0 , ds [2 ], - ns [2 ]],
@@ -235,7 +232,7 @@ def get_zooms(self):
235232 For four-dimensional files, a fourth zoom is included, equal to the
236233 repetition time (TR) in ms.
237234
238- To access only the spatial zooms, use `hdr['voxelsize ']`.
235+ To access only the spatial zooms, use `hdr['delta ']`.
239236
240237 Returns
241238 -------
@@ -244,7 +241,7 @@ def get_zooms(self):
244241 '''
245242 # Do not return time zoom (TR) if 3D image
246243 tzoom = (self ['tr' ],)[:self ._ndims () > 3 ]
247- return tuple (self ._structarr ['voxelsize ' ]) + tzoom
244+ return tuple (self ._structarr ['delta ' ]) + tzoom
248245
249246 def set_zooms (self , zooms ):
250247 ''' Set zooms into header fields
@@ -266,7 +263,7 @@ def set_zooms(self, zooms):
266263 raise HeaderDataError ('Expecting %d zoom values' % ndims )
267264 if np .any (zooms <= 0 ):
268265 raise HeaderDataError ('zooms must be positive' )
269- hdr ['voxelsize ' ] = zooms [:3 ]
266+ hdr ['delta ' ] = zooms [:3 ]
270267 if len (zooms ) == 4 :
271268 hdr ['tr' ] = zooms [3 ]
272269
@@ -292,7 +289,7 @@ def set_data_shape(self, shape):
292289 if len (shape ) > 4 :
293290 raise ValueError ("Shape may be at most 4 dimensional" )
294291 self ._structarr ['dims' ] = shape + (1 ,) * (4 - len (shape ))
295- self ._structarr ['voxelsize ' ] = 1
292+ self ._structarr ['delta ' ] = 1
296293
297294 def get_data_bytespervox (self ):
298295 ''' Get the number of bytes per voxel of the data
@@ -357,22 +354,18 @@ def default_structarr(klass, endianness=None):
357354 structarr ['version' ] = 1
358355 structarr ['dims' ] = 1
359356 structarr ['type' ] = 3
360- structarr ['ras_good' ] = 1
361- structarr ['voxelsize' ] = 1
362- structarr ['x_ras' ][0 ] = - 1
363- structarr ['y_ras' ][2 ] = 1
364- structarr ['z_ras' ][1 ] = - 1
357+ structarr ['goodRASFlag' ] = 1
358+ structarr ['delta' ] = 1
359+ structarr ['Mdc' ] = [[- 1 , 0 , 0 ], [0 , 0 , 1 ], [0 , - 1 , 0 ]]
365360 return structarr
366361
367362 def _set_affine_default (self ):
368- ''' If ras_good flag is 0, set the default affine
363+ ''' If goodRASFlag is 0, set the default affine
369364 '''
370- self ._structarr ['ras_good' ] = 1
371- self ._structarr ['voxelsize' ] = 1
372- self ._structarr ['x_ras' ] = [[- 1 ], [0 ], [0 ]]
373- self ._structarr ['y_ras' ] = [[0 ], [0 ], [1 ]]
374- self ._structarr ['z_ras' ] = [[0 ], [- 1 ], [0 ]]
375- self ._structarr ['c_ras' ] = 0
365+ self ._structarr ['goodRASFlag' ] = 1
366+ self ._structarr ['delta' ] = 1
367+ self ._structarr ['Mdc' ] = [[- 1 , 0 , 0 ], [0 , 0 , 1 ], [0 , - 1 , 0 ]]
368+ self ._structarr ['Pxyz_c' ] = 0
376369
377370 def writehdr_to (self , fileobj ):
378371 ''' Write header to fileobj
@@ -416,35 +409,20 @@ def writeftr_to(self, fileobj):
416409
417410 class _HeaderData :
418411 """ Provide interface to deprecated MGHHeader fields"""
419- renamed = {'goodRASFlag' : 'ras_good' ,
420- 'delta' : 'voxelsize' }
421412 def __init__ (self , structarr ):
422413 self ._structarr = structarr
423414
424415 def __getitem__ (self , item ):
425416 sa = self ._structarr
426- if item == 'Mdc' :
427- return np .hstack ((sa ['x_ras' ], sa ['y_ras' ], sa ['z_ras' ])).T
428- elif item == 'Pxyz_c' :
429- return sa ['c_ras' ][:, 0 ]
430- elif item == 'mrparams' :
417+ if item == 'mrparams' :
431418 return np .hstack ((sa ['tr' ], sa ['flip_angle' ], sa ['te' ], sa ['ti' ]))
432- elif item in self .renamed :
433- item = self .renamed [item ]
434419 return sa [item ]
435420
436421 def __setitem__ (self , item , val ):
437422 sa = self ._structarr
438- if item == 'Mdc' :
439- sa ['x_ras' ][:, 0 ], sa ['y_ras' ][:, 0 ], sa ['z_ras' ][:, 0 ] = val
440- elif item == 'Pxyz_c' :
441- sa ['c_ras' ][:, 0 ] = val
442- elif item == 'mrparams' :
443- return sa ['tr' ], sa ['flip_angle' ], sa ['te' ], sa ['ti' ] = val
444- else :
445- if item in self .renamed .values ():
446- item = {v : k for k , v in self .renamed .items ()}[item ]
447- sa [item ] = val
423+ if item == 'mrparams' :
424+ sa ['tr' ], sa ['flip_angle' ], sa ['te' ], sa ['ti' ] = val
425+ sa [item ] = val
448426
449427 @property
450428 @deprecate_with_version ('_header_data is deprecated.\n '
@@ -457,12 +435,12 @@ def _header_data(self):
457435 return self ._HeaderData (self ._structarr )
458436
459437 def __getitem__ (self , item ):
460- if item in ( 'goodRASFlag' , 'delta' , 'Mdc' , 'Pxyz_c' , ' mrparams') :
438+ if item == ' mrparams' :
461439 return self ._header_data [item ]
462440 return super (MGHHeader , self ).__getitem__ (item )
463441
464442 def __setitem__ (self , item , value ):
465- if item in ( 'goodRASFlag' , 'delta' , 'Mdc' , 'Pxyz_c' , ' mrparams') :
443+ if item == ' mrparams' :
466444 self ._header_data [item ] = value
467445 super (MGHHeader , self ).__setitem__ (item , value )
468446
@@ -627,17 +605,17 @@ def _write_data(self, mghfile, data, header):
627605 def _affine2header (self ):
628606 """ Unconditionally set affine into the header """
629607 hdr = self ._header
630- shape = np .array (self ._dataobj .shape [:3 ]). reshape ( - 1 , 1 )
608+ shape = np .array (self ._dataobj .shape [:3 ])
631609
632610 # for more information, go through save_mgh.m in FreeSurfer dist
633611 voxelsize = voxel_sizes (self ._affine )
634612 Mdc = self ._affine [:3 , :3 ] / voxelsize
635- c_ras = self ._affine .dot (np .vstack ((shape / 2.0 , [1 ])))[:3 ]
613+ c_ras = self ._affine .dot (np .hstack ((shape / 2.0 , [1 ])))[:3 ]
636614
637615 # Assign after we've had a chance to raise exceptions
638- hdr ['voxelsize ' ] = voxelsize
639- hdr ['x_ras' ][:, 0 ], hdr [ 'y_ras' ][:, 0 ], hdr [ 'z_ras' ][:, 0 ] = Mdc .T
640- hdr ['c_ras ' ] = c_ras
616+ hdr ['delta ' ] = voxelsize
617+ hdr ['Mdc' ] = Mdc .T
618+ hdr ['Pxyz_c ' ] = c_ras
641619
642620
643621load = MGHImage .load
0 commit comments