Skip to content

Commit cc52223

Browse files
committed
Merge pull request #315 from effigies/ico7
MRG: Automatically reshape FreeSurfer ico7 niftis Tried to follow in the footsteps of f53c168. Presents programmer with data object equivalent to an MGH, leaving header intact for writing to file.
2 parents e8aef7d + 51cc7de commit cc52223

File tree

4 files changed

+64
-12
lines changed

4 files changed

+64
-12
lines changed

nibabel-data/nitest-freesurfer

Submodule nitest-freesurfer updated from 0110860 to df9ccc6

nibabel/nifti1.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -698,16 +698,26 @@ def get_data_shape(self):
698698
Allows for freesurfer hack for large vectors described in
699699
https://github.com/nipy/nibabel/issues/100 and
700700
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/save_nifti.m?spec=svn5022&r=5022#77
701+
702+
Allows for freesurfer hack for 7th order icosahedron surface described
703+
in
704+
https://github.com/nipy/nibabel/issues/309
705+
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/load_nifti.m?r=8776#86
706+
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/save_nifti.m?r=8776#50
701707
'''
702708
shape = super(Nifti1Header, self).get_data_shape()
703709
# Apply freesurfer hack for vector
704-
if shape != (-1, 1, 1): # Normal case
710+
if shape == (-1, 1, 1):
711+
vec_len = int(self._structarr['glmin'])
712+
if vec_len == 0:
713+
raise HeaderDataError('-1 in dim[1] but 0 in glmin; '
714+
'inconsistent freesurfer type header?')
715+
return (vec_len, 1, 1)
716+
# Apply freesurfer hack for ico7 surface
717+
elif shape == (27307, 1, 6):
718+
return (163842, 1, 1)
719+
else: # Normal case
705720
return shape
706-
vec_len = int(self._structarr['glmin'])
707-
if vec_len == 0:
708-
raise HeaderDataError('-1 in dim[1] but 0 in glmin; inconsistent '
709-
'freesurfer type header?')
710-
return (vec_len, 1, 1)
711721

712722
def set_data_shape(self, shape):
713723
''' Set shape of data
@@ -725,12 +735,22 @@ def set_data_shape(self, shape):
725735
Applies freesurfer hack for large vectors described in
726736
https://github.com/nipy/nibabel/issues/100 and
727737
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/save_nifti.m?spec=svn5022&r=5022#77
738+
739+
Allows for freesurfer hack for 7th order icosahedron surface described
740+
in
741+
https://github.com/nipy/nibabel/issues/309
742+
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/load_nifti.m?r=8776#86
743+
https://code.google.com/p/fieldtrip/source/browse/trunk/external/freesurfer/save_nifti.m?r=8776#50
728744
'''
729-
# Apply freesurfer hack for vector
730745
hdr = self._structarr
731746
shape = tuple(shape)
732-
if (len(shape) == 3 and shape[1:] == (1, 1) and
733-
shape[0] > np.iinfo(hdr['dim'].dtype.base).max): # Freesurfer case
747+
748+
# Apply freesurfer hack for ico7 surface
749+
if shape == (163842, 1, 1):
750+
shape = (27307, 1, 6)
751+
# Apply freesurfer hack for vector
752+
elif (len(shape) == 3 and shape[1:] == (1, 1) and
753+
shape[0] > np.iinfo(hdr['dim'].dtype.base).max):
734754
try:
735755
hdr['glmin'] = shape[0]
736756
except OverflowError:

nibabel/tests/test_nifti1.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
Nifti1Pair, Nifti1Extension, Nifti1Extensions,
2525
data_type_codes, extension_codes, slice_order_codes)
2626

27+
from ..freesurfer import load as mghload
28+
2729
from .test_arraywriters import rt_err_estimate, IUINT_TYPES
2830
from .test_helpers import bytesio_filemap, bytesio_round_trip
31+
from .nibabel_data import get_nibabel_data, needs_nibabel_data
2932

3033
from numpy.testing import (assert_array_equal, assert_array_almost_equal,
3134
assert_almost_equal)
@@ -242,7 +245,7 @@ def test_magic_offset_checks(self):
242245
'file nifti1; setting to minimum value '
243246
'of ' + str(hdr.single_vox_offset))
244247

245-
def test_freesurfer_hack(self):
248+
def test_freesurfer_large_vector_hack(self):
246249
# For large vector images, Freesurfer appears to set dim[1] to -1 and
247250
# then use glmin for the vector length (an i4)
248251
HC = self.header_class
@@ -288,6 +291,31 @@ def test_freesurfer_hack(self):
288291
hdr.set_data_shape(constructor(shape))
289292
assert_equal(hdr.get_data_shape(), shape)
290293

294+
@needs_nibabel_data('nitest-freesurfer')
295+
def test_freesurfer_ico7_hack(self):
296+
HC = self.header_class
297+
hdr = HC()
298+
# Test that using ico7 shape automatically uses factored dimensions
299+
hdr.set_data_shape((163842, 1, 1))
300+
assert_array_equal(hdr._structarr['dim'][1:4], np.array([27307, 1, 6]))
301+
# Test consistency of data in .mgh and mri_convert produced .nii
302+
nitest_path = os.path.join(get_nibabel_data(), 'nitest-freesurfer')
303+
mgh = mghload(os.path.join(nitest_path, 'fsaverage', 'surf',
304+
'lh.orig.avg.area.mgh'))
305+
nii = load(os.path.join(nitest_path, 'derivative', 'fsaverage', 'surf',
306+
'lh.orig.avg.area.nii'))
307+
assert_equal(mgh.shape, nii.shape)
308+
assert_array_equal(mgh.get_data(), nii.get_data())
309+
assert_array_equal(nii.header._structarr['dim'][1:4],
310+
np.array([27307, 1, 6]))
311+
# Test writing produces consistent nii files
312+
with InTemporaryDirectory():
313+
nii.to_filename('test.nii')
314+
nii2 = load('test.nii')
315+
assert_equal(nii.shape, nii2.shape)
316+
assert_array_equal(nii.get_data(), nii2.get_data())
317+
assert_array_equal(nii.get_affine(), nii2.get_affine())
318+
291319
def test_qform_sform(self):
292320
HC = self.header_class
293321
hdr = HC()

nibabel/tests/test_nifti2.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ class _Nifti2Mixin(object):
3434
sizeof_hdr = Nifti2Header.sizeof_hdr
3535
quat_dtype = np.float64
3636

37-
def test_freesurfer_hack(self):
37+
def test_freesurfer_large_vector_hack(self):
38+
# Disable this check
39+
pass
40+
41+
def test_freesurfer_ico7_hack(self):
3842
# Disable this check
3943
pass
4044

0 commit comments

Comments
 (0)