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