diff --git a/nitransforms/io/afni.py b/nitransforms/io/afni.py index 1e878563..b197c4ed 100644 --- a/nitransforms/io/afni.py +++ b/nitransforms/io/afni.py @@ -135,10 +135,10 @@ def to_ras(self, moving=None, reference=None): if reference is not None and _is_oblique(ref_aff := _ensure_image(reference).affine): pre_rotation = _cardinal_rotation(ref_aff, True) if moving is not None and _is_oblique(mov_aff := _ensure_image(moving).affine): - post_rotation = _cardinal_rotation(mov_aff, True) + post_rotation = _cardinal_rotation(mov_aff, False) return np.stack([ - post_rotation @ xfm.to_ras() @ pre_rotation + post_rotation @ (xfm.to_ras() @ pre_rotation) for xfm in self.xforms ]) @@ -152,14 +152,22 @@ def to_string(self): if line.strip() ] strings += lines - return "\n".join(strings) + return "\n".join(strings + [""]) @classmethod def from_ras(cls, ras, moving=None, reference=None): """Create an ITK affine from a nitransform's RAS+ matrix.""" _self = cls() + + pre_rotation = post_rotation = np.eye(4) + + if reference is not None and _is_oblique(ref_aff := _ensure_image(reference).affine): + pre_rotation = _cardinal_rotation(ref_aff, False) + if moving is not None and _is_oblique(mov_aff := _ensure_image(moving).affine): + post_rotation = _cardinal_rotation(mov_aff, True) + _self.xforms = [ - cls._inner_type.from_ras(ras[i, ...], moving=moving, reference=reference) + cls._inner_type.from_ras(post_rotation @ ras[i, ...] @ pre_rotation) for i in range(ras.shape[0]) ] return _self diff --git a/nitransforms/tests/data/affine-LAS.afni-array b/nitransforms/tests/data/affine-LAS.afni-array new file mode 120000 index 00000000..27d48851 --- /dev/null +++ b/nitransforms/tests/data/affine-LAS.afni-array @@ -0,0 +1 @@ +affine-RAS.afni-array \ No newline at end of file diff --git a/nitransforms/tests/data/affine-LPS.afni-array b/nitransforms/tests/data/affine-LPS.afni-array new file mode 120000 index 00000000..27d48851 --- /dev/null +++ b/nitransforms/tests/data/affine-LPS.afni-array @@ -0,0 +1 @@ +affine-RAS.afni-array \ No newline at end of file diff --git a/nitransforms/tests/data/affine-oblique.afni-array b/nitransforms/tests/data/affine-oblique.afni-array new file mode 120000 index 00000000..27d48851 --- /dev/null +++ b/nitransforms/tests/data/affine-oblique.afni-array @@ -0,0 +1 @@ +affine-RAS.afni-array \ No newline at end of file diff --git a/nitransforms/tests/test_io.py b/nitransforms/tests/test_io.py index 982167f5..bcee9198 100644 --- a/nitransforms/tests/test_io.py +++ b/nitransforms/tests/test_io.py @@ -208,9 +208,6 @@ def test_Linear_common(tmpdir, data_path, sw, image_orientation, get_testdata): fname = f"affine-{image_orientation}.{sw}{ext}" - if sw == "afni-array": - fname.replace(image_orientation, "RAS") - # Test the transform loaders are implemented xfm = factory.from_filename(data_path / fname) @@ -228,7 +225,7 @@ def test_Linear_common(tmpdir, data_path, sw, image_orientation, get_testdata): # Test from_ras RAS = from_matvec(euler2mat(x=0.9, y=0.001, z=0.001), [4.0, 2.0, -1.0]) if sw == "afni-array": - RAS = [RAS, RAS] + RAS = np.array([RAS, RAS]) xfm = factory.from_ras(RAS, reference=reference, moving=moving) assert np.allclose(xfm.to_ras(reference=reference, moving=moving), RAS)