Skip to content

Commit e13ec29

Browse files
committed
RF - new interface for get / set affine routines
1 parent fd43bc5 commit e13ec29

File tree

2 files changed

+281
-57
lines changed

2 files changed

+281
-57
lines changed

nibabel/tests/test_trackvis.py

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
''' Testing trackvis module '''
2+
from functools import partial
3+
import warnings
24

35
import numpy as np
46

57
from ..py3k import BytesIO, asbytes
68
from .. import trackvis as tv
9+
from ..orientations import aff2axcodes
710
from ..volumeutils import native_code, swapped_code
11+
from ..checkwarns import ErrorWarnings, IgnoreWarnings
812

913
from nose.tools import assert_true, assert_false, assert_equal, assert_raises
1014

@@ -165,55 +169,118 @@ def test_empty_header():
165169

166170

167171
def test_get_affine():
172+
# Test get affine behavior, including pending deprecation
168173
hdr = tv.empty_header()
174+
# Using version 1 affine is not a good idea because is fragile and not
175+
# very useful. The default atleast_v2=None mode raises a FutureWarning
176+
with ErrorWarnings():
177+
assert_raises(FutureWarning, tv.aff_from_hdr, hdr)
178+
# testing the old behavior
179+
old_afh = partial(tv.aff_from_hdr, atleast_v2=False)
169180
# default header gives useless affine
170-
assert_array_equal(tv.aff_from_hdr(hdr),
181+
assert_array_equal(old_afh(hdr),
171182
np.diag([0,0,0,1]))
172183
hdr['voxel_size'] = 1
173-
assert_array_equal(tv.aff_from_hdr(hdr),
184+
assert_array_equal(old_afh(hdr),
174185
np.diag([0,0,0,1]))
175186
# DICOM direction cosines
176187
hdr['image_orientation_patient'] = [1,0,0,0,1,0]
177-
assert_array_equal(tv.aff_from_hdr(hdr),
188+
assert_array_equal(old_afh(hdr),
178189
np.diag([-1,-1,1,1]))
179190
# RAS direction cosines
180191
hdr['image_orientation_patient'] = [-1,0,0,0,-1,0]
181-
assert_array_equal(tv.aff_from_hdr(hdr),
192+
assert_array_equal(old_afh(hdr),
182193
np.eye(4))
183194
# translations
184195
hdr['origin'] = [1,2,3]
185196
exp_aff = np.eye(4)
186197
exp_aff[:3,3] = [-1,-2,3]
187-
assert_array_equal(tv.aff_from_hdr(hdr),
198+
assert_array_equal(old_afh(hdr),
188199
exp_aff)
200+
# check against voxel order. This one works
201+
hdr['voxel_order'] = ''.join(aff2axcodes(exp_aff))
202+
assert_equal(hdr['voxel_order'], 'RAS')
203+
assert_array_equal(old_afh(hdr), exp_aff)
204+
# This one doesn't
205+
hdr['voxel_order'] = 'LAS'
206+
assert_raises(tv.HeaderError, old_afh, hdr)
207+
# This one does work because the routine allows the final dimension to
208+
# be flipped to try and match the voxel order
209+
hdr['voxel_order'] = 'RAI'
210+
exp_aff = exp_aff * [[1,1,-1,1]]
211+
assert_array_equal(old_afh(hdr), exp_aff)
212+
# Check round trip case for flipped and unflipped, when positive voxels
213+
# only allowed. This checks that the flipping heuristic works.
214+
flipped_aff = exp_aff
215+
unflipped_aff = exp_aff * [1,1,-1,1]
216+
for in_aff, o_codes in ((unflipped_aff, 'RAS'),
217+
(flipped_aff, 'RAI')):
218+
hdr = tv.empty_header()
219+
tv.aff_to_hdr(in_aff, hdr, pos_vox=True, set_order=True)
220+
# Unset easier option
221+
hdr['vox_to_ras'] = 0
222+
assert_equal(hdr['voxel_order'], o_codes)
223+
# Check it came back the way we wanted
224+
assert_array_equal(old_afh(hdr), in_aff)
225+
# Check that the default case matches atleast_v2=False case
226+
with IgnoreWarnings():
227+
assert_array_equal(tv.aff_from_hdr(hdr), flipped_aff)
189228
# now use the easier vox_to_ras field
190229
hdr = tv.empty_header()
191230
aff = np.eye(4)
192231
aff[:3,:] = np.arange(12).reshape(3,4)
193232
hdr['vox_to_ras'] = aff
194-
assert_array_equal(tv.aff_from_hdr(hdr), aff)
233+
# Pass v2 flag explicitly to avoid warnings
234+
assert_array_equal(tv.aff_from_hdr(hdr, atleast_v2=False), aff)
195235
# mappings work too
196236
d = {'version': 1,
197-
'voxel_size': np.array([1,2,3]),
198-
'image_orientation_patient': np.array([1,0,0,0,1,0]),
199-
'origin': np.array([10,11,12])}
200-
aff = tv.aff_from_hdr(d)
237+
'voxel_size': np.array([1,2,3]),
238+
'image_orientation_patient': np.array([1,0,0,0,1,0]),
239+
'origin': np.array([10,11,12])}
240+
aff = tv.aff_from_hdr(d, atleast_v2=False)
201241

202242

203243
def test_aff_to_hdr():
204-
for version in (1, 2):
205-
hdr = {'version': version}
206-
affine = np.diag([1,2,3,1])
207-
affine[:3,3] = [10,11,12]
244+
# The behavior is changing soon, change signaled by FutureWarnings
245+
# This is the call to get the old behavior
246+
old_a2h = partial(tv.aff_to_hdr, pos_vox=False, set_order=False)
247+
hdr = {'version': 1}
248+
affine = np.diag([1,2,3,1])
249+
affine[:3,3] = [10,11,12]
250+
old_a2h(affine, hdr)
251+
assert_array_almost_equal(tv.aff_from_hdr(hdr, atleast_v2=False), affine)
252+
# put flip into affine
253+
aff2 = affine.copy()
254+
aff2[:,2] *=-1
255+
old_a2h(aff2, hdr)
256+
# Historically we flip the first axis if there is a negative determinant
257+
assert_array_almost_equal(hdr['voxel_size'], [-1,2,3])
258+
assert_array_almost_equal(tv.aff_from_hdr(hdr, atleast_v2=False), aff2)
259+
# Test that default mode raises DeprecationWarning
260+
with ErrorWarnings():
261+
assert_raises(FutureWarning, tv.aff_to_hdr, affine, hdr)
262+
assert_raises(FutureWarning, tv.aff_to_hdr, affine, hdr, None, None)
263+
assert_raises(FutureWarning, tv.aff_to_hdr, affine, hdr, False, None)
264+
assert_raises(FutureWarning, tv.aff_to_hdr, affine, hdr, None, False)
265+
# And has same effect as above
266+
with IgnoreWarnings():
208267
tv.aff_to_hdr(affine, hdr)
209-
assert_array_almost_equal(tv.aff_from_hdr(hdr), affine)
210-
# put flip into affine
211-
aff2 = affine.copy()
212-
aff2[:,2] *=-1
213-
tv.aff_to_hdr(aff2, hdr)
214-
assert_array_almost_equal(tv.aff_from_hdr(hdr), aff2)
215-
if version == 2:
216-
assert_array_almost_equal(hdr['vox_to_ras'], aff2)
268+
assert_array_almost_equal(tv.aff_from_hdr(hdr, atleast_v2=False), affine)
269+
# Check pos_vox and order flags
270+
for hdr in ({}, {'version':2}, {'version':1}):
271+
tv.aff_to_hdr(aff2, hdr, pos_vox=True, set_order=False)
272+
assert_array_equal(hdr['voxel_size'], [1, 2, 3])
273+
assert_false('voxel_order' in hdr)
274+
tv.aff_to_hdr(aff2, hdr, pos_vox=False, set_order=True)
275+
assert_array_equal(hdr['voxel_size'], [-1, 2, 3])
276+
assert_equal(hdr['voxel_order'], 'RAI')
277+
tv.aff_to_hdr(aff2, hdr, pos_vox=True, set_order=True)
278+
assert_array_equal(hdr['voxel_size'], [1, 2, 3])
279+
assert_equal(hdr['voxel_order'], 'RAI')
280+
if 'version' in hdr and hdr['version'] == 1:
281+
assert_false('vox_to_ras' in hdr)
282+
else:
283+
assert_array_equal(hdr['vox_to_ras'], aff2)
217284

218285

219286
def test_tv_class():
@@ -236,19 +303,28 @@ def test_tv_class():
236303
# check that we check input values
237304
out_f.truncate(0); out_f.seek(0)
238305
assert_raises(tv.HeaderError,
239-
tv.TrackvisFile,
240-
[],{'id_string':'not OK'})
306+
tv.TrackvisFile,
307+
[],{'id_string':'not OK'})
241308
assert_raises(tv.HeaderError,
242-
tv.TrackvisFile,
243-
[],{'version': 3})
309+
tv.TrackvisFile,
310+
[],{'version': 3})
244311
assert_raises(tv.HeaderError,
245-
tv.TrackvisFile,
246-
[],{'hdr_size':0})
312+
tv.TrackvisFile,
313+
[],{'hdr_size':0})
247314
affine = np.diag([1,2,3,1])
248315
affine[:3,3] = [10,11,12]
249-
tvf.set_affine(affine)
250-
assert_true(np.all(tvf.get_affine() == affine))
316+
# affine methods will raise same warnings and errors as function
317+
with ErrorWarnings():
318+
assert_raises(FutureWarning, tvf.set_affine, affine)
319+
assert_raises(FutureWarning, tvf.set_affine, affine, None, None)
320+
assert_raises(FutureWarning, tvf.set_affine, affine, False, None)
321+
assert_raises(FutureWarning, tvf.set_affine, affine, None, False)
322+
assert_raises(FutureWarning, tvf.get_affine)
323+
assert_raises(FutureWarning, tvf.get_affine, None)
324+
tvf.set_affine(affine, pos_vox=True, set_order=True)
325+
aff = tvf.get_affine(atleast_v2=True)
326+
assert_array_almost_equal(aff, affine)
251327
# Test that we raise an error with an iterator
252328
assert_raises(tv.TrackvisFileError,
253-
tv.TrackvisFile,
254-
iter([]))
329+
tv.TrackvisFile,
330+
iter([]))

0 commit comments

Comments
 (0)