Skip to content

Commit 71b79b5

Browse files
markhymerseffigies
authored andcommitted
Make as_closest_canonical also update dim_info
At present, we leave misleading information in dim_info when using as_closest_canonical. This patch makes us update the information based on our axis re-ordering and adds tests that it has been done. Signed-off-by: Mark Hymers <[email protected]>
1 parent acc5c07 commit 71b79b5

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

nibabel/funcs.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,18 @@ def as_closest_canonical(img, enforce_diag=False):
224224
# we need to transform the data
225225
arr = img.get_data()
226226
t_arr = apply_orientation(arr, ornt)
227-
return img.__class__(t_arr, out_aff, img.header)
227+
# Also apply the transform to the dim_info fields
228+
new_hdr = img.header.copy()
229+
new_dim = list(new_hdr.get_dim_info())
230+
for idx, value in enumerate(new_dim):
231+
# For each value, leave as None if it was that way,
232+
# otherwise check where we have mapped it to
233+
if value is None:
234+
continue
235+
new_dim[idx] = np.where(ornt[:, 0] == idx)[0]
236+
new_hdr.set_dim_info(*new_dim)
237+
238+
return img.__class__(t_arr, out_aff, new_hdr)
228239

229240

230241
def _aff_is_diag(aff):

nibabel/tests/test_funcs.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,21 @@ def test_closest_canonical():
131131
arr = np.arange(24).reshape((2, 3, 4, 1))
132132
# no funky stuff, returns same thing
133133
img = Nifti1Image(arr, np.eye(4))
134+
# set freq/phase/slice dim so that we can check that we
135+
# re-order them properly
136+
img.header.set_dim_info(0, 1, 2)
134137
xyz_img = as_closest_canonical(img)
135138
assert_true(img is xyz_img)
139+
136140
# a axis flip
137141
img = Nifti1Image(arr, np.diag([-1, 1, 1, 1]))
142+
img.header.set_dim_info(0, 1, 2)
138143
xyz_img = as_closest_canonical(img)
139144
assert_false(img is xyz_img)
145+
assert_true(img.header.get_dim_info() == xyz_img.header.get_dim_info())
140146
out_arr = xyz_img.get_data()
141147
assert_array_equal(out_arr, np.flipud(arr))
148+
142149
# no error for enforce_diag in this case
143150
xyz_img = as_closest_canonical(img, True)
144151
# but there is if the affine is not diagonal
@@ -150,3 +157,22 @@ def test_closest_canonical():
150157
assert_true(img is xyz_img)
151158
# it's still not diagnonal
152159
assert_raises(OrientationError, as_closest_canonical, img, True)
160+
161+
# an axis swap
162+
aff = np.diag([1, 0, 0, 1])
163+
aff[1, 2] = 1; aff[2, 1] = 1
164+
img = Nifti1Image(arr, aff)
165+
img.header.set_dim_info(0, 1, 2)
166+
167+
xyz_img = as_closest_canonical(img)
168+
assert_false(img is xyz_img)
169+
# Check both the original and new objects
170+
assert_true(img.header.get_dim_info() == (0, 1, 2))
171+
assert_true(xyz_img.header.get_dim_info() == (0, 2, 1))
172+
out_arr = xyz_img.get_data()
173+
assert_array_equal(out_arr, np.transpose(arr, (0, 2, 1, 3)))
174+
175+
# same axis swap but with None dim info (except for slice dim)
176+
img.header.set_dim_info(None, None, 2)
177+
xyz_img = as_closest_canonical(img)
178+
assert_true(xyz_img.header.get_dim_info() == (None, None, 1))

0 commit comments

Comments
 (0)