|
1 | 1 | import os
|
| 2 | +import sys |
2 | 3 | import copy
|
3 | 4 | import unittest
|
4 |
| -import numpy as np |
5 | 5 | from os.path import join as pjoin
|
6 | 6 |
|
| 7 | +import numpy as np |
| 8 | + |
7 | 9 | from nibabel.externals.six import BytesIO
|
8 | 10 |
|
9 | 11 | from nibabel.testing import data_path
|
@@ -99,82 +101,94 @@ def test_load_complex_file(self):
|
99 | 101 | trk = TrkFile.load(DATA['complex_trk_fname'], lazy_load=lazy_load)
|
100 | 102 | assert_tractogram_equal(trk.tractogram, DATA['complex_tractogram'])
|
101 | 103 |
|
| 104 | + def trk_with_bytes(self, trk_key='simple_trk_fname', endian='<'): |
| 105 | + """ Return example trk file bytes and struct view onto bytes """ |
| 106 | + with open(DATA[trk_key], 'rb') as fobj: |
| 107 | + trk_bytes = fobj.read() |
| 108 | + dt = trk_module.header_2_dtype.newbyteorder(endian) |
| 109 | + trk_struct = np.ndarray((1,), dt, buffer=trk_bytes) |
| 110 | + trk_struct.flags.writeable = True |
| 111 | + return trk_struct, trk_bytes |
| 112 | + |
102 | 113 | def test_load_file_with_wrong_information(self):
|
103 | 114 | trk_file = open(DATA['simple_trk_fname'], 'rb').read()
|
104 | 115 |
|
105 | 116 | # Simulate a TRK file where `count` was not provided.
|
106 |
| - count = np.array(0, dtype="int32").tostring() |
107 |
| - new_trk_file = trk_file[:1000-12] + count + trk_file[1000-8:] |
108 |
| - trk = TrkFile.load(BytesIO(new_trk_file), lazy_load=False) |
| 117 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 118 | + trk_struct[Field.NB_STREAMLINES] = 0 |
| 119 | + trk = TrkFile.load(BytesIO(trk_bytes), lazy_load=False) |
109 | 120 | assert_tractogram_equal(trk.tractogram, DATA['simple_tractogram'])
|
110 | 121 |
|
111 | 122 | # Simulate a TRK where `vox_to_ras` is not recorded (i.e. all zeros).
|
112 |
| - vox_to_ras = np.zeros((4, 4), dtype=np.float32).tostring() |
113 |
| - new_trk_file = trk_file[:440] + vox_to_ras + trk_file[440+64:] |
| 123 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 124 | + trk_struct[Field.VOXEL_TO_RASMM] = np.zeros((4, 4)) |
114 | 125 | with clear_and_catch_warnings(record=True, modules=[trk_module]) as w:
|
115 |
| - trk = TrkFile.load(BytesIO(new_trk_file)) |
| 126 | + trk = TrkFile.load(BytesIO(trk_bytes)) |
116 | 127 | assert_equal(len(w), 1)
|
117 | 128 | assert_true(issubclass(w[0].category, HeaderWarning))
|
118 | 129 | assert_true("identity" in str(w[0].message))
|
119 | 130 | assert_array_equal(trk.affine, np.eye(4))
|
120 | 131 |
|
121 | 132 | # Simulate a TRK where `vox_to_ras` is invalid.
|
122 |
| - vox_to_ras = np.zeros((4, 4), dtype=np.float32) |
123 |
| - vox_to_ras[3, 3] = 1 |
124 |
| - vox_to_ras = vox_to_ras.tostring() |
125 |
| - new_trk_file = trk_file[:440] + vox_to_ras + trk_file[440+64:] |
| 133 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 134 | + trk_struct[Field.VOXEL_TO_RASMM] = np.diag([0, 0, 0, 1]) |
126 | 135 | with clear_and_catch_warnings(record=True, modules=[trk_module]) as w:
|
127 |
| - assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file)) |
| 136 | + assert_raises(HeaderError, TrkFile.load, BytesIO(trk_bytes)) |
128 | 137 |
|
129 | 138 | # Simulate a TRK file where `voxel_order` was not provided.
|
130 |
| - voxel_order = np.zeros(1, dtype="|S3").tostring() |
131 |
| - new_trk_file = trk_file[:948] + voxel_order + trk_file[948+3:] |
| 139 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 140 | + trk_struct[Field.VOXEL_ORDER] = b'' |
132 | 141 | with clear_and_catch_warnings(record=True, modules=[trk_module]) as w:
|
133 |
| - TrkFile.load(BytesIO(new_trk_file)) |
| 142 | + TrkFile.load(BytesIO(trk_bytes)) |
134 | 143 | assert_equal(len(w), 1)
|
135 | 144 | assert_true(issubclass(w[0].category, HeaderWarning))
|
136 | 145 | assert_true("LPS" in str(w[0].message))
|
137 | 146 |
|
138 | 147 | # Simulate a TRK file with an unsupported version.
|
139 |
| - version = np.int32(123).tostring() |
140 |
| - new_trk_file = trk_file[:992] + version + trk_file[992+4:] |
141 |
| - assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file)) |
| 148 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 149 | + trk_struct['version'] = 123 |
| 150 | + assert_raises(HeaderError, TrkFile.load, BytesIO(trk_bytes)) |
142 | 151 |
|
143 | 152 | # Simulate a TRK file with a wrong hdr_size.
|
144 |
| - hdr_size = np.int32(1234).tostring() |
145 |
| - new_trk_file = trk_file[:996] + hdr_size + trk_file[996+4:] |
146 |
| - assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file)) |
| 153 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 154 | + trk_struct['hdr_size'] = 1234 |
| 155 | + assert_raises(HeaderError, TrkFile.load, BytesIO(trk_bytes)) |
147 | 156 |
|
148 | 157 | # Simulate a TRK file with a wrong scalar_name.
|
149 |
| - trk_file = open(DATA['complex_trk_fname'], 'rb').read() |
150 |
| - noise = np.int32(42).tostring() |
151 |
| - new_trk_file = trk_file[:47] + noise + trk_file[47+4:] |
152 |
| - assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file)) |
| 158 | + trk_struct, trk_bytes = self.trk_with_bytes('complex_trk_fname') |
| 159 | + trk_struct['scalar_name'][0, 0] = b'colors\x003\x004' |
| 160 | + assert_raises(HeaderError, TrkFile.load, BytesIO(trk_bytes)) |
153 | 161 |
|
154 | 162 | # Simulate a TRK file with a wrong property_name.
|
155 |
| - noise = np.int32(42).tostring() |
156 |
| - new_trk_file = trk_file[:254] + noise + trk_file[254+4:] |
157 |
| - assert_raises(HeaderError, TrkFile.load, BytesIO(new_trk_file)) |
| 163 | + trk_struct, trk_bytes = self.trk_with_bytes('complex_trk_fname') |
| 164 | + trk_struct['property_name'][0, 0] = b'colors\x003\x004' |
| 165 | + assert_raises(HeaderError, TrkFile.load, BytesIO(trk_bytes)) |
158 | 166 |
|
159 | 167 | 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:] |
| 168 | + # Simulate and test a TRK (version 1). |
| 169 | + # First check that setting the RAS affine works in version 2. |
| 170 | + trk_struct, trk_bytes = self.trk_with_bytes() |
| 171 | + trk_struct[Field.VOXEL_TO_RASMM] = np.diag([2, 3, 4, 1]) |
| 172 | + trk = TrkFile.load(BytesIO(trk_bytes)) |
| 173 | + assert_array_equal(trk.affine, np.diag([2, 3, 4, 1])) |
| 174 | + # Next check that affine assumed identity if version 1. |
| 175 | + trk_struct['version'] = 1 |
165 | 176 | with clear_and_catch_warnings(record=True, modules=[trk_module]) as w:
|
166 |
| - trk = TrkFile.load(BytesIO(new_trk_file)) |
| 177 | + trk = TrkFile.load(BytesIO(trk_bytes)) |
167 | 178 | assert_equal(len(w), 1)
|
168 | 179 | assert_true(issubclass(w[0].category, HeaderWarning))
|
169 | 180 | assert_true("identity" in str(w[0].message))
|
170 | 181 | assert_array_equal(trk.affine, np.eye(4))
|
171 | 182 | assert_array_equal(trk.header['version'], 1)
|
172 | 183 |
|
173 | 184 | def test_load_complex_file_in_big_endian(self):
|
174 |
| - trk_file = open(DATA['complex_trk_big_endian_fname'], 'rb').read() |
| 185 | + trk_struct, trk_bytes = self.trk_with_bytes( |
| 186 | + 'complex_trk_big_endian_fname', endian='>') |
175 | 187 | # We use hdr_size as an indicator of little vs big endian.
|
176 |
| - hdr_size_big_endian = np.array(1000, dtype=">i4").tostring() |
177 |
| - assert_equal(trk_file[996:996+4], hdr_size_big_endian) |
| 188 | + good_orders = '>' if sys.byteorder == 'little' else '>=' |
| 189 | + hdr_size = trk_struct['hdr_size'] |
| 190 | + assert_true(hdr_size.dtype.byteorder in good_orders) |
| 191 | + assert_equal(hdr_size, 1000) |
178 | 192 |
|
179 | 193 | for lazy_load in [False, True]:
|
180 | 194 | trk = TrkFile.load(DATA['complex_trk_big_endian_fname'],
|
|
0 commit comments