Skip to content

Commit 99b56b5

Browse files
committed
BF: Supports reading TRK (version 1)
1 parent 7e08d25 commit 99b56b5

File tree

2 files changed

+32
-39
lines changed

2 files changed

+32
-39
lines changed

nibabel/streamlines/tests/test_trk.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,20 @@ def test_load_file_with_wrong_information(self):
156156
new_trk_file = trk_file[:254] + noise + trk_file[254+4:]
157157
assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file))
158158

159+
def test_load_trk_version_1(self):
160+
trk_file = open(DATA['simple_trk_fname'], 'rb').read()
161+
162+
# Simulate a TRK (version 1).
163+
version = np.array(1, dtype=np.int32).tostring()
164+
new_trk_file = trk_file[:992] + version + trk_file[992+4:]
165+
with clear_and_catch_warnings(record=True, modules=[trk_module]) as w:
166+
trk = TrkFile.load(BytesIO(new_trk_file))
167+
assert_equal(len(w), 1)
168+
assert_true(issubclass(w[0].category, HeaderWarning))
169+
assert_true("identity" in str(w[0].message))
170+
assert_array_equal(trk.affine, np.eye(4))
171+
assert_array_equal(trk.header['version'], 1)
172+
159173
def test_load_complex_file_in_big_endian(self):
160174
trk_file = open(DATA['complex_trk_big_endian_fname'], 'rb').read()
161175
# We use hdr_size as an indicator of little vs big endian.

nibabel/streamlines/trk.py

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -26,36 +26,11 @@
2626
MAX_NB_NAMED_SCALARS_PER_POINT = 10
2727
MAX_NB_NAMED_PROPERTIES_PER_STREAMLINE = 10
2828

29-
# See http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
30-
header_1_dtd = [(Field.MAGIC_NUMBER, 'S6'),
31-
(Field.DIMENSIONS, 'h', 3),
32-
(Field.VOXEL_SIZES, 'f4', 3),
33-
(Field.ORIGIN, 'f4', 3),
34-
(Field.NB_SCALARS_PER_POINT, 'h'),
35-
('scalar_name', 'S20', MAX_NB_NAMED_SCALARS_PER_POINT),
36-
(Field.NB_PROPERTIES_PER_STREAMLINE, 'h'),
37-
('property_name', 'S20',
38-
MAX_NB_NAMED_PROPERTIES_PER_STREAMLINE),
39-
('reserved', 'S508'),
40-
(Field.VOXEL_ORDER, 'S4'),
41-
('pad2', 'S4'),
42-
('image_orientation_patient', 'f4', 6),
43-
('pad1', 'S2'),
44-
('invert_x', 'S1'),
45-
('invert_y', 'S1'),
46-
('invert_z', 'S1'),
47-
('swap_xy', 'S1'),
48-
('swap_yz', 'S1'),
49-
('swap_zx', 'S1'),
50-
(Field.NB_STREAMLINES, 'i4'),
51-
('version', 'i4'),
52-
('hdr_size', 'i4'),
53-
]
54-
55-
# Version 2 adds a 4x4 matrix giving the affine transformtation going
29+
# Version 2 adds a 4x4 matrix giving the affine transformation going
5630
# from voxel coordinates in the referenced 3D voxel matrix, to xyz
5731
# coordinates (axes L->R, P->A, I->S). If (0 based) value [3, 3] from
5832
# this matrix is 0, this means the matrix is not recorded.
33+
# See http://docs.scipy.org/doc/numpy/reference/arrays.dtypes.html
5934
header_2_dtd = [(Field.MAGIC_NUMBER, 'S6'),
6035
(Field.DIMENSIONS, 'h', 3),
6136
(Field.VOXEL_SIZES, 'f4', 3),
@@ -83,7 +58,6 @@
8358
]
8459

8560
# Full header numpy dtypes
86-
header_1_dtype = np.dtype(header_1_dtd)
8761
header_2_dtype = np.dtype(header_2_dtd)
8862

8963

@@ -584,8 +558,8 @@ def _read_header(fileobj):
584558
TrkFile.HEADER_SIZE))
585559

586560
if header_rec['version'] == 1:
587-
header_rec = np.fromstring(string=header_str,
588-
dtype=header_1_dtype)
561+
# There is no 4x4 matrix for voxel to RAS transformation.
562+
header_rec[Field.VOXEL_TO_RASMM] = np.zeros((4, 4))
589563
elif header_rec['version'] == 2:
590564
pass # Nothing more to do.
591565
else:
@@ -724,12 +698,17 @@ def __str__(self):
724698
hdr_field = getattr(Field, attr)
725699
if hdr_field in vars:
726700
vars[attr] = vars[hdr_field]
727-
vars['scalar_names'] = '\n '.join([asstr(s)
728-
for s in vars['scalar_name']
729-
if len(s) > 0])
730-
vars['property_names'] = "\n ".join([asstr(s)
731-
for s in vars['property_name']
732-
if len(s) > 0])
701+
702+
nb_scalars = self.header[Field.NB_SCALARS_PER_POINT]
703+
scalar_names = [asstr(s)
704+
for s in vars['scalar_name'][:nb_scalars]
705+
if len(s) > 0]
706+
vars['scalar_names'] = '\n '.join(scalar_names)
707+
nb_properties = self.header[Field.NB_PROPERTIES_PER_STREAMLINE]
708+
property_names = [asstr(s)
709+
for s in vars['property_name'][:nb_properties]
710+
if len(s) > 0]
711+
vars['property_names'] = "\n ".join(property_names)
733712
# Make all byte strings into strings
734713
# Fixes recursion error on Python 3.3
735714
vars = dict((k, asstr(v) if hasattr(v, 'decode') else v)
@@ -739,11 +718,11 @@ def __str__(self):
739718
v.{version}
740719
dim: {DIMENSIONS}
741720
voxel_sizes: {VOXEL_SIZES}
742-
orgin: {ORIGIN}
721+
origin: {ORIGIN}
743722
nb_scalars: {NB_SCALARS_PER_POINT}
744-
scalar_name:\n {scalar_names}
723+
scalar_names:\n {scalar_names}
745724
nb_properties: {NB_PROPERTIES_PER_STREAMLINE}
746-
property_name:\n {property_names}
725+
property_names:\n {property_names}
747726
vox_to_world:\n{VOXEL_TO_RASMM}
748727
voxel_order: {VOXEL_ORDER}
749728
image_orientation_patient: {image_orientation_patient}

0 commit comments

Comments
 (0)