2
2
# vi: set ft=python sts=4 ts=4 sw=4 et:
3
3
"""Tests of the transform module."""
4
4
import os
5
- import numpy as np
6
- from numpy .testing import assert_array_equal , assert_almost_equal , \
7
- assert_array_almost_equal
8
5
import pytest
6
+ import numpy as np
7
+ from subprocess import check_call
9
8
10
- from nibabel .loadsave import load as loadimg
11
- from nibabel .nifti1 import Nifti1Image
9
+ import nibabel as nb
12
10
from nibabel .eulerangles import euler2mat
13
11
from nibabel .affines import from_matvec
14
- from ..patched import shape_zoom_affine
15
- from .. import linear as nbl
16
- from nibabel .testing import (assert_equal , assert_not_equal , assert_true ,
17
- assert_false , assert_raises ,
18
- suppress_warnings , assert_dt_equal )
19
12
from nibabel .tmpdirs import InTemporaryDirectory
13
+ from .. import linear as nbl
14
+ from .utils import assert_affines_by_filename
20
15
21
- data_path = os .path .join (os .path .dirname (__file__ ), 'data' )
22
- SOMEONES_ANATOMY = os .path .join (data_path , 'someones_anatomy.nii.gz' )
16
+ TESTS_BORDER_TOLERANCE = 0.05
17
+ APPLY_LINEAR_CMD = {
18
+ 'fsl' : """\
19
+ flirt -setbackground 0 -interp nearestneighbour -in {moving} -ref {reference} \
20
+ -applyxfm -init {transform} -out resampled.nii.gz\
21
+ """ .format ,
22
+ 'itk' : """\
23
+ antsApplyTransforms -d 3 -r {reference} -i {moving} \
24
+ -o resampled.nii.gz -n NearestNeighbor -t {transform} --float\
25
+ """ .format ,
26
+ 'afni' : """\
27
+ 3dAllineate -base {reference} -input {moving} \
28
+ -prefix resampled.nii.gz -1Dmatrix_apply {transform} -final NN\
29
+ """ .format ,
30
+ }
23
31
24
32
25
- @pytest .mark .parametrize ('image_orientation' , ['RAS' , 'LAS' , 'LPS' , 'oblique' ])
26
- def test_affines_save (image_orientation ):
27
- """Check implementation of exporting affines to formats."""
28
- # Generate test transform
29
- img = loadimg (SOMEONES_ANATOMY )
30
- imgaff = img .affine
31
-
32
- if image_orientation == 'LAS' :
33
- newaff = imgaff .copy ()
34
- newaff [0 , 0 ] *= - 1.0
35
- newaff [0 , 3 ] = imgaff .dot (np .hstack ((np .array (img .shape [:3 ]) - 1 , 1.0 )))[0 ]
36
- img = Nifti1Image (np .flip (img .get_fdata (), 0 ), newaff , img .header )
37
- elif image_orientation == 'LPS' :
38
- newaff = imgaff .copy ()
39
- newaff [0 , 0 ] *= - 1.0
40
- newaff [1 , 1 ] *= - 1.0
41
- newaff [:2 , 3 ] = imgaff .dot (np .hstack ((np .array (img .shape [:3 ]) - 1 , 1.0 )))[:2 ]
42
- img = Nifti1Image (np .flip (np .flip (img .get_fdata (), 0 ), 1 ), newaff , img .header )
43
- elif image_orientation == 'oblique' :
44
- A = shape_zoom_affine (img .shape , img .header .get_zooms (), x_flip = False )
45
- R = from_matvec (euler2mat (x = 0.09 , y = 0.001 , z = 0.001 ))
46
- newaff = R .dot (A )
47
- img = Nifti1Image (img .get_fdata (), newaff , img .header )
48
- img .header .set_qform (newaff , 1 )
49
- img .header .set_sform (newaff , 1 )
33
+ @pytest .mark .parametrize ('image_orientation' , [
34
+ 'RAS' , 'LAS' , 'LPS' , # 'oblique',
35
+ ])
36
+ @pytest .mark .parametrize ('sw_tool' , ['itk' , 'fsl' , 'afni' ])
37
+ def test_linear_load (tmpdir , data_path , get_data , image_orientation , sw_tool ):
38
+ """Check implementation of loading affines from formats."""
39
+ tmpdir .chdir ()
50
40
41
+ img = get_data [image_orientation ]
42
+ img .to_filename ('img.nii.gz' )
43
+
44
+ # Generate test transform
51
45
T = from_matvec (euler2mat (x = 0.9 , y = 0.001 , z = 0.001 ), [4.0 , 2.0 , - 1.0 ])
46
+ xfm = nbl .Affine (T )
47
+ xfm .reference = img
48
+
49
+ ext = ''
50
+ if sw_tool == 'itk' :
51
+ ext = '.tfm'
52
+
53
+ fname = 'affine-%s.%s%s' % (image_orientation , sw_tool , ext )
54
+ xfm_fname = os .path .join (data_path , fname )
55
+
56
+ if sw_tool == 'fsl' :
57
+ with pytest .raises ("ValueError" ):
58
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ])
59
+ with pytest .raises ("ValueError" ):
60
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ],
61
+ reference = 'img.nii.gz' )
62
+ with pytest .raises ("ValueError" ):
63
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ],
64
+ moving = 'img.nii.gz' )
65
+
66
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ],
67
+ moving = 'img.nii.gz' , reference = 'img.nii.gz' )
68
+ if sw_tool == 'afni' :
69
+ with pytest .raises ("ValueError" ):
70
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ])
71
+
72
+ loaded = nbl .load (xfm_fname , fmt = fname .split ('.' )[- 1 ],
73
+ reference = 'img.nii.gz' )
52
74
75
+ assert loaded == xfm
76
+
77
+
78
+ @pytest .mark .parametrize ('image_orientation' , [
79
+ 'RAS' , 'LAS' , 'LPS' , # 'oblique',
80
+ ])
81
+ @pytest .mark .parametrize ('sw_tool' , ['itk' , 'fsl' , 'afni' ])
82
+ def test_linear_save (data_path , get_data , image_orientation , sw_tool ):
83
+ """Check implementation of exporting affines to formats."""
84
+ img = get_data [image_orientation ]
85
+ # Generate test transform
86
+ T = from_matvec (euler2mat (x = 0.9 , y = 0.001 , z = 0.001 ), [4.0 , 2.0 , - 1.0 ])
53
87
xfm = nbl .Affine (T )
54
88
xfm .reference = img
55
89
56
- itk = nbl .load (os .path .join (data_path , 'affine-%s-itk.tfm' % image_orientation ),
57
- fmt = 'itk' )
58
- fsl = np .loadtxt (os .path .join (data_path , 'affine-%s.fsl' % image_orientation ))
59
- afni = np .loadtxt (os .path .join (data_path , 'affine-%s.afni' % image_orientation ))
90
+ ext = ''
91
+ if sw_tool == 'itk' :
92
+ ext = '.tfm'
60
93
61
94
with InTemporaryDirectory ():
62
- xfm .to_filename ('M.tfm' , fmt = 'itk' )
63
- xfm .to_filename ('M.fsl' , fmt = 'fsl' )
64
- xfm .to_filename ('M.afni' , fmt = 'afni' )
95
+ xfm_fname1 = 'M.%s%s' % (sw_tool , ext )
96
+ xfm .to_filename (xfm_fname1 , fmt = sw_tool )
97
+
98
+ xfm_fname2 = os .path .join (
99
+ data_path , 'affine-%s.%s%s' % (image_orientation , sw_tool , ext ))
100
+ assert_affines_by_filename (xfm_fname1 , xfm_fname2 )
101
+
102
+
103
+ @pytest .mark .parametrize ('image_orientation' , [
104
+ 'RAS' , 'LAS' , 'LPS' , # 'oblique',
105
+ ])
106
+ @pytest .mark .parametrize ('sw_tool' , ['itk' , 'fsl' , 'afni' ])
107
+ def test_apply_linear_transform (tmpdir , data_path , get_data , image_orientation , sw_tool ):
108
+ """Check implementation of exporting affines to formats."""
109
+ tmpdir .chdir ()
110
+
111
+ img = get_data [image_orientation ]
112
+ # Generate test transform
113
+ T = from_matvec (euler2mat (x = 0.9 , y = 0.001 , z = 0.001 ), [4.0 , 2.0 , - 1.0 ])
114
+ xfm = nbl .Affine (T )
115
+ xfm .reference = img
116
+
117
+ ext = ''
118
+ if sw_tool == 'itk' :
119
+ ext = '.tfm'
65
120
66
- nb_itk = nbl . load ( 'M.tfm' , fmt = 'itk ' )
67
- nb_fsl = np . loadtxt ( 'M.fsl' )
68
- nb_afni = np . loadtxt ( 'M.afni' )
121
+ img . to_filename ( 'img.nii.gz ' )
122
+ xfm_fname = 'M.%s%s' % ( sw_tool , ext )
123
+ xfm . to_filename ( xfm_fname , fmt = sw_tool )
69
124
70
- assert_equal (itk , nb_itk )
71
- assert_almost_equal (fsl , nb_fsl )
72
- assert_almost_equal (afni , nb_afni )
125
+ cmd = APPLY_LINEAR_CMD [sw_tool ](
126
+ transform = os .path .abspath (xfm_fname ),
127
+ reference = os .path .abspath ('img.nii.gz' ),
128
+ moving = os .path .abspath ('img.nii.gz' ))
129
+ exit_code = check_call ([cmd ], shell = True )
130
+ assert exit_code == 0
131
+ sw_moved = nb .load ('resampled.nii.gz' )
73
132
74
- # Create version not aligned to canonical
133
+ nt_moved = xfm .resample (img , order = 0 )
134
+ diff = sw_moved .get_fdata () - nt_moved .get_fdata ()
135
+ # A certain tolerance is necessary because of resampling at borders
136
+ assert (np .abs (diff ) > 1e-3 ).sum () / diff .size < TESTS_BORDER_TOLERANCE
0 commit comments