Skip to content

Commit 317b1cc

Browse files
committed
RF+DOC+TEST: tck format.
1 parent 2b87c36 commit 317b1cc

File tree

8 files changed

+422
-338
lines changed

8 files changed

+422
-338
lines changed

nibabel/streamlines/tck.py

Lines changed: 308 additions & 279 deletions
Large diffs are not rendered by default.

nibabel/streamlines/tests/test_streamlines.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from .test_tractogram import assert_tractogram_equal
1717
from ..tractogram import Tractogram, LazyTractogram
1818
from ..tractogram_file import TractogramFile, ExtensionWarning
19+
from .. import FORMATS
1920
from .. import trk
2021

2122
DATA = {}
@@ -24,11 +25,13 @@
2425
def setup():
2526
global DATA
2627
DATA['empty_filenames'] = [pjoin(data_path, "empty" + ext)
27-
for ext in nib.streamlines.FORMATS.keys()]
28+
for ext in FORMATS.keys()]
2829
DATA['simple_filenames'] = [pjoin(data_path, "simple" + ext)
29-
for ext in nib.streamlines.FORMATS.keys()]
30+
for ext in FORMATS.keys()]
3031
DATA['complex_filenames'] = [pjoin(data_path, "complex" + ext)
31-
for ext in nib.streamlines.FORMATS.keys()]
32+
for ext, cls in FORMATS.items()
33+
if (cls.SUPPORTS_DATA_PER_POINT or
34+
cls.SUPPORTS_DATA_PER_STREAMLINE)]
3235

3336
DATA['streamlines'] = [np.arange(1*3, dtype="f4").reshape((1, 3)),
3437
np.arange(2*3, dtype="f4").reshape((2, 3)),
@@ -84,23 +87,23 @@ def test_is_supported_detect_format():
8487
assert_true(nib.streamlines.detect_format("") is None)
8588

8689
# Valid file without extension
87-
for tfile_cls in nib.streamlines.FORMATS.values():
90+
for tfile_cls in FORMATS.values():
8891
f = BytesIO()
8992
f.write(tfile_cls.MAGIC_NUMBER)
9093
f.seek(0, os.SEEK_SET)
9194
assert_true(nib.streamlines.is_supported(f))
9295
assert_true(nib.streamlines.detect_format(f) is tfile_cls)
9396

9497
# Wrong extension but right magic number
95-
for tfile_cls in nib.streamlines.FORMATS.values():
98+
for tfile_cls in FORMATS.values():
9699
with tempfile.TemporaryFile(mode="w+b", suffix=".txt") as f:
97100
f.write(tfile_cls.MAGIC_NUMBER)
98101
f.seek(0, os.SEEK_SET)
99102
assert_true(nib.streamlines.is_supported(f))
100103
assert_true(nib.streamlines.detect_format(f) is tfile_cls)
101104

102105
# Good extension but wrong magic number
103-
for ext, tfile_cls in nib.streamlines.FORMATS.items():
106+
for ext, tfile_cls in FORMATS.items():
104107
with tempfile.TemporaryFile(mode="w+b", suffix=ext) as f:
105108
f.write(b"pass")
106109
f.seek(0, os.SEEK_SET)
@@ -113,13 +116,13 @@ def test_is_supported_detect_format():
113116
assert_true(nib.streamlines.detect_format(f) is None)
114117

115118
# Good extension, string only
116-
for ext, tfile_cls in nib.streamlines.FORMATS.items():
119+
for ext, tfile_cls in FORMATS.items():
117120
f = "my_tractogram" + ext
118121
assert_true(nib.streamlines.is_supported(f))
119122
assert_equal(nib.streamlines.detect_format(f), tfile_cls)
120123

121124
# Extension should not be case-sensitive.
122-
for ext, tfile_cls in nib.streamlines.FORMATS.items():
125+
for ext, tfile_cls in FORMATS.items():
123126
f = "my_tractogram" + ext.upper()
124127
assert_true(nib.streamlines.detect_format(f) is tfile_cls)
125128

@@ -208,7 +211,7 @@ def test_save_tractogram_file(self):
208211

209212
def test_save_empty_file(self):
210213
tractogram = Tractogram(affine_to_rasmm=np.eye(4))
211-
for ext, cls in nib.streamlines.FORMATS.items():
214+
for ext, cls in FORMATS.items():
212215
with InTemporaryDirectory():
213216
filename = 'streamlines' + ext
214217
nib.streamlines.save(tractogram, filename)
@@ -218,7 +221,7 @@ def test_save_empty_file(self):
218221
def test_save_simple_file(self):
219222
tractogram = Tractogram(DATA['streamlines'],
220223
affine_to_rasmm=np.eye(4))
221-
for ext, cls in nib.streamlines.FORMATS.items():
224+
for ext, cls in FORMATS.items():
222225
with InTemporaryDirectory():
223226
filename = 'streamlines' + ext
224227
nib.streamlines.save(tractogram, filename)
@@ -231,7 +234,7 @@ def test_save_complex_file(self):
231234
DATA['data_per_point'],
232235
affine_to_rasmm=np.eye(4))
233236

234-
for ext, cls in nib.streamlines.FORMATS.items():
237+
for ext, cls in FORMATS.items():
235238
with InTemporaryDirectory():
236239
filename = 'streamlines' + ext
237240

@@ -240,12 +243,17 @@ def test_save_complex_file(self):
240243
nib.streamlines.save(complex_tractogram, filename)
241244

242245
# If streamlines format does not support saving data
243-
# per point or data per streamline, a warning message
246+
# per point or data per streamline, warning messages
244247
# should be issued.
245-
if not (cls.SUPPORTS_DATA_PER_POINT and
246-
cls.SUPPORTS_DATA_PER_STREAMLINE):
247-
assert_equal(len(w), 1)
248-
assert_true(issubclass(w[0].category, Warning))
248+
nb_expected_warnings = 0
249+
if not cls.SUPPORTS_DATA_PER_POINT:
250+
nb_expected_warnings += 1
251+
if not cls.SUPPORTS_DATA_PER_STREAMLINE:
252+
nb_expected_warnings += 1
253+
254+
assert_equal(len(w), nb_expected_warnings)
255+
for i in range(nb_expected_warnings):
256+
assert_true(issubclass(w[i].category, Warning))
249257

250258
tractogram = Tractogram(DATA['streamlines'],
251259
affine_to_rasmm=np.eye(4))

nibabel/streamlines/tests/test_tck.py

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,142 @@
11
import os
22
import unittest
33
import numpy as np
4+
from os.path import join as pjoin
45

56
from nibabel.externals.six import BytesIO
67

7-
from nibabel.testing import suppress_warnings, clear_and_catch_warnings
8-
from nibabel.testing import assert_arrays_equal, check_iteration
9-
from nose.tools import assert_equal, assert_raises, assert_true
8+
from nose.tools import assert_equal
109

10+
from nibabel.testing import data_path
1111
from .test_tractogram import assert_tractogram_equal
12-
from ..tractogram import Tractogram, LazyTractogram
13-
from ..tractogram_file import DataError, HeaderError, HeaderWarning
12+
from ..tractogram import Tractogram
1413

1514
from ..tck import TckFile
1615

17-
DATA_PATH = os.path.join(os.path.dirname(__file__), 'data')
1816

17+
DATA = {}
1918

20-
class TestTCK(unittest.TestCase):
2119

22-
def setUp(self):
23-
self.empty_tck_filename = os.path.join(DATA_PATH, "empty.tck")
24-
# simple.tck contains only streamlines
25-
self.simple_tck_filename = os.path.join(DATA_PATH, "simple.tck")
20+
def setup():
21+
global DATA
22+
23+
DATA['empty_tck_fname'] = pjoin(data_path, "empty.tck")
24+
# simple.trk contains only streamlines
25+
DATA['simple_tck_fname'] = pjoin(data_path, "simple.tck")
26+
DATA['simple_tck_big_endian_fname'] = pjoin(data_path,
27+
"simple_big_endian.tck")
28+
# standard.trk contains only streamlines
29+
DATA['standard_tck_fname'] = pjoin(data_path, "standard.tck")
30+
# complex.trk contains streamlines, scalars and properties
31+
# DATA['complex_tck_fname'] = pjoin(data_path, "complex.tck")
32+
33+
DATA['streamlines'] = [np.arange(1*3, dtype="f4").reshape((1, 3)),
34+
np.arange(2*3, dtype="f4").reshape((2, 3)),
35+
np.arange(5*3, dtype="f4").reshape((5, 3))]
36+
37+
# DATA['fa'] = [np.array([[0.2]], dtype="f4"),
38+
# np.array([[0.3],
39+
# [0.4]], dtype="f4"),
40+
# np.array([[0.5],
41+
# [0.6],
42+
# [0.6],
43+
# [0.7],
44+
# [0.8]], dtype="f4")]
45+
46+
# DATA['colors'] = [np.array([(1, 0, 0)]*1, dtype="f4"),
47+
# np.array([(0, 1, 0)]*2, dtype="f4"),
48+
# np.array([(0, 0, 1)]*5, dtype="f4")]
49+
50+
# DATA['mean_curvature'] = [np.array([1.11], dtype="f4"),
51+
# np.array([2.11], dtype="f4"),
52+
# np.array([3.11], dtype="f4")]
2653

27-
self.streamlines = [np.arange(1*3, dtype="f4").reshape((1, 3)),
28-
np.arange(2*3, dtype="f4").reshape((2, 3)),
29-
np.arange(5*3, dtype="f4").reshape((5, 3))]
54+
# DATA['mean_torsion'] = [np.array([1.22], dtype="f4"),
55+
# np.array([2.22], dtype="f4"),
56+
# np.array([3.22], dtype="f4")]
3057

31-
self.empty_tractogram = Tractogram()
32-
self.simple_tractogram = Tractogram(self.streamlines)
58+
# DATA['mean_colors'] = [np.array([1, 0, 0], dtype="f4"),
59+
# np.array([0, 1, 0], dtype="f4"),
60+
# np.array([0, 0, 1], dtype="f4")]
61+
62+
# DATA['data_per_point'] = {'colors': DATA['colors'],
63+
# 'fa': DATA['fa']}
64+
# DATA['data_per_streamline'] = {'mean_curvature': DATA['mean_curvature'],
65+
# 'mean_torsion': DATA['mean_torsion'],
66+
# 'mean_colors': DATA['mean_colors']}
67+
68+
DATA['empty_tractogram'] = Tractogram(affine_to_rasmm=np.eye(4))
69+
DATA['simple_tractogram'] = Tractogram(DATA['streamlines'],
70+
affine_to_rasmm=np.eye(4))
71+
# DATA['complex_tractogram'] = Tractogram(DATA['streamlines'],
72+
# DATA['data_per_streamline'],
73+
# DATA['data_per_point'],
74+
# affine_to_rasmm=np.eye(4))
75+
76+
77+
class TestTCK(unittest.TestCase):
3378

3479
def test_load_empty_file(self):
3580
for lazy_load in [False, True]:
36-
tck = TckFile.load(self.empty_tck_filename, lazy_load=lazy_load)
37-
assert_tractogram_equal(tck.tractogram, self.empty_tractogram)
81+
trk = TckFile.load(DATA['empty_tck_fname'], lazy_load=lazy_load)
82+
assert_tractogram_equal(trk.tractogram, DATA['empty_tractogram'])
3883

3984
def test_load_simple_file(self):
4085
for lazy_load in [False, True]:
41-
tck = TckFile.load(self.simple_tck_filename, lazy_load=lazy_load)
42-
assert_tractogram_equal(tck.tractogram, self.simple_tractogram)
86+
trk = TckFile.load(DATA['simple_tck_fname'], lazy_load=lazy_load)
87+
assert_tractogram_equal(trk.tractogram, DATA['simple_tractogram'])
4388

4489
def test_write_empty_file(self):
45-
tractogram = Tractogram()
90+
tractogram = Tractogram(affine_to_rasmm=np.eye(4))
4691

4792
tck_file = BytesIO()
4893
tck = TckFile(tractogram)
4994
tck.save(tck_file)
5095
tck_file.seek(0, os.SEEK_SET)
5196

52-
loaded_tck = TckFile.load(tck_file)
53-
assert_tractogram_equal(loaded_tck.tractogram, tractogram)
97+
new_tck = TckFile.load(tck_file)
98+
assert_tractogram_equal(new_tck.tractogram, tractogram)
5499

55-
loaded_tck_orig = TckFile.load(self.empty_tck_filename)
56-
assert_tractogram_equal(loaded_tck.tractogram, loaded_tck_orig.tractogram)
100+
new_tck_orig = TckFile.load(DATA['empty_tck_fname'])
101+
assert_tractogram_equal(new_tck.tractogram, new_tck_orig.tractogram)
57102

58103
tck_file.seek(0, os.SEEK_SET)
59-
assert_equal(tck_file.read(), open(self.empty_tck_filename, 'rb').read())
104+
assert_equal(tck_file.read(),
105+
open(DATA['empty_tck_fname'], 'rb').read())
60106

61107
def test_write_simple_file(self):
62-
tractogram = Tractogram(self.streamlines)
108+
tractogram = Tractogram(DATA['streamlines'],
109+
affine_to_rasmm=np.eye(4))
63110

64111
tck_file = BytesIO()
65112
tck = TckFile(tractogram)
66113
tck.save(tck_file)
67114
tck_file.seek(0, os.SEEK_SET)
68115

69-
loaded_tck = TckFile.load(tck_file)
70-
assert_tractogram_equal(loaded_tck.tractogram, tractogram)
116+
new_tck = TckFile.load(tck_file)
117+
assert_tractogram_equal(new_tck.tractogram, tractogram)
71118

72-
loaded_tck_orig = TckFile.load(self.simple_tck_filename)
73-
assert_tractogram_equal(loaded_tck.tractogram, loaded_tck_orig.tractogram)
119+
new_tck_orig = TckFile.load(DATA['simple_tck_fname'])
120+
assert_tractogram_equal(new_tck.tractogram, new_tck_orig.tractogram)
74121

75122
tck_file.seek(0, os.SEEK_SET)
76-
assert_equal(tck_file.read(), open(self.simple_tck_filename, 'rb').read())
123+
assert_equal(tck_file.read(),
124+
open(DATA['simple_tck_fname'], 'rb').read())
77125

78126
def test_load_write_file(self):
79-
for filename in [self.empty_tck_filename, self.simple_tck_filename]:
127+
for fname in [DATA['empty_tck_fname'],
128+
DATA['simple_tck_fname']]:
80129
for lazy_load in [False, True]:
81-
tck = TckFile.load(filename, lazy_load=lazy_load)
130+
tck = TckFile.load(fname, lazy_load=lazy_load)
82131
tck_file = BytesIO()
83132
tck.save(tck_file)
84133

85-
loaded_tck = TckFile.load(filename, lazy_load=False)
134+
loaded_tck = TckFile.load(fname, lazy_load=False)
86135
assert_tractogram_equal(loaded_tck.tractogram, tck.tractogram)
87136

88-
# tck_file.seek(0, os.SEEK_SET)
89-
# assert_equal(tck_file.read(), open(filename, 'rb').read())
90-
91137
# Save tractogram that has an affine_to_rasmm.
92138
for lazy_load in [False, True]:
93-
tck = TckFile.load(self.simple_tck_filename, lazy_load=lazy_load)
139+
tck = TckFile.load(DATA['simple_tck_fname'], lazy_load=lazy_load)
94140
affine = np.eye(4)
95141
affine[0, 0] *= -1 # Flip in X
96142
tractogram = Tractogram(tck.streamlines, affine_to_rasmm=affine)

nibabel/streamlines/tests/test_trk.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,6 @@ def test_load_write_file(self):
296296
new_trk = TrkFile.load(fname, lazy_load=False)
297297
assert_tractogram_equal(new_trk.tractogram, trk.tractogram)
298298

299-
trk_file.seek(0, os.SEEK_SET)
300-
301299
def test_load_write_LPS_file(self):
302300
# Load the RAS and LPS version of the standard.
303301
trk_RAS = TrkFile.load(DATA['standard_trk_fname'], lazy_load=False)

nibabel/streamlines/tractogram_file.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class HeaderWarning(Warning):
1414
""" Base class for warnings about tractogram file header. """
1515

1616

17+
class DataWarning(Warning):
18+
""" Base class for warnings about tractogram file data. """
19+
20+
1721
class HeaderError(Exception):
1822
""" Raised when a tractogram file header contains invalid information. """
1923

nibabel/streamlines/trk.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,6 @@ class TrkFile(TractogramFile):
220220
221221
Notes
222222
-----
223-
224223
TrackVis (so its file format: TRK) considers the streamline coordinate
225224
(0,0,0) to be in the corner of the voxel whereas NiBabel's streamlines
226225
internal representation (Voxel space) assumes (0,0,0) to be in the
@@ -597,7 +596,7 @@ def _read_header(fileobj):
597596
# Keep the file position where the data begin.
598597
header['_offset_data'] = f.tell()
599598

600-
# Set the file position where it was, if it was previously open
599+
# Set the file position where it was, if it was previously open.
601600
if start_position is not None:
602601
fileobj.seek(start_position, os.SEEK_SET)
603602

File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)