Skip to content

Commit 2a9e96f

Browse files
Merge pull request #461 from jaeilepp/fix-surf
MRG: Fix to surface reading with new quad. Follow up to PR #460 which implemented read of surface data. The data format is actually different when reading new quad files. Use a file from freesurfer that has this format (added in the nibabel-data submodules) to test.
2 parents 01d3a92 + 9b66562 commit 2a9e96f

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

nibabel/freesurfer/io.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def _fread3_many(fobj, n):
4646

4747

4848
def _read_volume_info(fobj):
49+
"""Helper for reading the footer from a surface file."""
4950
volume_info = OrderedDict()
5051
head = np.fromfile(fobj, '>i4', 1)
5152
if not np.array_equal(head, [20]): # Read two bytes more
@@ -106,13 +107,17 @@ def read_geometry(filepath, read_metadata=False, read_stamp=False):
106107
"""
107108
volume_info = OrderedDict()
108109

110+
TRIANGLE_MAGIC = 16777214
111+
QUAD_MAGIC = 16777215
112+
NEW_QUAD_MAGIC = 16777213
109113
with open(filepath, "rb") as fobj:
110114
magic = _fread3(fobj)
111-
if magic in (16777215, 16777213): # Quad file
115+
if magic in (QUAD_MAGIC, NEW_QUAD_MAGIC): # Quad file
112116
nvert = _fread3(fobj)
113117
nquad = _fread3(fobj)
114-
coords = np.fromfile(fobj, ">i2", nvert * 3).astype(np.float)
115-
coords = coords.reshape(-1, 3) / 100.0
118+
(fmt, div) = (">i2", 100.) if magic == QUAD_MAGIC else (">f4", 1.)
119+
coords = np.fromfile(fobj, fmt, nvert * 3).astype(np.float) / div
120+
coords = coords.reshape(-1, 3)
116121
quads = _fread3_many(fobj, nquad * 4)
117122
quads = quads.reshape(nquad, 4)
118123
#
@@ -132,7 +137,7 @@ def read_geometry(filepath, read_metadata=False, read_stamp=False):
132137
faces[nface] = quad[0], quad[2], quad[3]
133138
nface += 1
134139

135-
elif magic == 16777214: # Triangle file
140+
elif magic == TRIANGLE_MAGIC: # Triangle file
136141
create_stamp = fobj.readline().rstrip(b'\n').decode('utf-8')
137142
fobj.readline()
138143
vnum = np.fromfile(fobj, ">i4", 1)[0]

nibabel/freesurfer/tests/test_io.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .. import (read_geometry, read_morph_data, read_annot, read_label,
1717
write_geometry, write_morph_data, write_annot)
1818

19-
from ...tests.nibabel_data import get_nibabel_data
19+
from ...tests.nibabel_data import get_nibabel_data, needs_nibabel_data
2020
from ...fileslice import strided_scalar
2121
from ...testing import clear_and_catch_warnings
2222

@@ -114,6 +114,23 @@ def test_geometry():
114114
np.testing.assert_array_equal(faces_swapped, faces)
115115

116116

117+
@freesurfer_test
118+
@needs_nibabel_data('nitest-freesurfer')
119+
def test_quad_geometry():
120+
"""Test IO of freesurfer quad files."""
121+
new_quad = pjoin(get_nibabel_data(), 'nitest-freesurfer', 'subjects',
122+
'bert', 'surf', 'lh.inflated.nofix')
123+
coords, faces = read_geometry(new_quad)
124+
assert_equal(0, faces.min())
125+
assert_equal(coords.shape[0], faces.max() + 1)
126+
with InTemporaryDirectory():
127+
new_path = 'test'
128+
write_geometry(new_path, coords, faces)
129+
coords2, faces2 = read_geometry(new_path)
130+
assert_equal(coords, coords2)
131+
assert_equal(faces, faces2)
132+
133+
117134
@freesurfer_test
118135
def test_morph_data():
119136
"""Test IO of morphometry data file (eg. curvature)."""

0 commit comments

Comments
 (0)