8
8
import numpy as np
9
9
import nibabel as nb
10
10
from nitransforms .resampling import apply
11
- from nitransforms .base import TransformError
11
+ from nitransforms .base import TransformError , ImageGrid
12
12
from nitransforms .io .base import TransformFileError
13
13
from nitransforms .nonlinear import (
14
14
BSplineFieldTransform ,
17
17
from ..io .itk import ITKDisplacementsField
18
18
19
19
20
+ SOME_TEST_POINTS = np .array ([
21
+ [0.0 , 0.0 , 0.0 ],
22
+ [1.0 , 2.0 , 3.0 ],
23
+ [10.0 , - 10.0 , 5.0 ],
24
+ [- 5.0 , 7.0 , - 2.0 ],
25
+ [12.0 , 0.0 , - 11.0 ],
26
+ ])
27
+
20
28
@pytest .mark .parametrize ("size" , [(20 , 20 , 20 ), (20 , 20 , 20 , 3 )])
21
29
def test_itk_disp_load (size ):
22
30
"""Checks field sizes."""
@@ -95,6 +103,10 @@ def test_bsplines_references(testdata_path):
95
103
)
96
104
97
105
106
+ @pytest .mark .xfail (
107
+ reason = "GH-267: disabled while debugging" ,
108
+ strict = False ,
109
+ )
98
110
def test_bspline (tmp_path , testdata_path ):
99
111
"""Cross-check B-Splines and deformation field."""
100
112
os .chdir (str (tmp_path ))
@@ -120,6 +132,66 @@ def test_bspline(tmp_path, testdata_path):
120
132
< 0.2
121
133
)
122
134
135
+ @pytest .mark .parametrize ("image_orientation" , ["RAS" , "LAS" , "LPS" , "oblique" ])
136
+ @pytest .mark .parametrize ("ongrid" , [True , False ])
137
+ def test_densefield_map (tmp_path , get_testdata , image_orientation , ongrid ):
138
+ """Create a constant displacement field and compare mappings."""
139
+
140
+ nii = get_testdata [image_orientation ]
141
+
142
+ # Create a reference centered at the origin with various axis orders/flips
143
+ shape = nii .shape
144
+ ref_affine = nii .affine .copy ()
145
+ reference = ImageGrid (nb .Nifti1Image (np .zeros (shape ), ref_affine , None ))
146
+ indices = reference .ndindex
147
+
148
+ gridpoints = reference .ras (indices )
149
+ points = gridpoints if ongrid else SOME_TEST_POINTS
150
+
151
+ coordinates = gridpoints .reshape (* shape , 3 )
152
+ deltas = np .stack ((
153
+ np .zeros (np .prod (shape ), dtype = "float32" ).reshape (shape ),
154
+ np .linspace (- 80 , 80 , num = np .prod (shape ), dtype = "float32" ).reshape (shape ),
155
+ np .linspace (- 50 , 50 , num = np .prod (shape ), dtype = "float32" ).reshape (shape ),
156
+ ), axis = - 1 )
157
+
158
+ atol = 1e-4 if image_orientation == "oblique" else 1e-7
159
+
160
+ # Build an identity transform (deltas)
161
+ id_xfm_deltas = DenseFieldTransform (reference = reference )
162
+ np .testing .assert_array_equal (coordinates , id_xfm_deltas ._field )
163
+ np .testing .assert_allclose (points , id_xfm_deltas .map (points ), atol = atol )
164
+
165
+ # Build an identity transform (deformation)
166
+ id_xfm_field = DenseFieldTransform (coordinates , is_deltas = False , reference = reference )
167
+ np .testing .assert_array_equal (coordinates , id_xfm_field ._field )
168
+ np .testing .assert_allclose (points , id_xfm_field .map (points ), atol = atol )
169
+
170
+ # Collapse to zero transform (deltas)
171
+ zero_xfm_deltas = DenseFieldTransform (- coordinates , reference = reference )
172
+ np .testing .assert_array_equal (np .zeros_like (zero_xfm_deltas ._field ), zero_xfm_deltas ._field )
173
+ np .testing .assert_allclose (np .zeros_like (points ), zero_xfm_deltas .map (points ), atol = atol )
174
+
175
+ # Collapse to zero transform (deformation)
176
+ zero_xfm_field = DenseFieldTransform (np .zeros_like (deltas ), is_deltas = False , reference = reference )
177
+ np .testing .assert_array_equal (np .zeros_like (zero_xfm_field ._field ), zero_xfm_field ._field )
178
+ np .testing .assert_allclose (np .zeros_like (points ), zero_xfm_field .map (points ), atol = atol )
179
+
180
+ # Now let's apply a transform
181
+ xfm = DenseFieldTransform (deltas , reference = reference )
182
+ np .testing .assert_array_equal (deltas , xfm ._deltas )
183
+ np .testing .assert_array_equal (coordinates + deltas , xfm ._field )
184
+
185
+ mapped = xfm .map (points )
186
+ nit_deltas = mapped - points
187
+
188
+ if ongrid :
189
+ mapped_image = mapped .reshape (* shape , 3 )
190
+ np .testing .assert_allclose (deltas + coordinates , mapped_image )
191
+ np .testing .assert_allclose (deltas , nit_deltas .reshape (* shape , 3 ), atol = 1e-4 )
192
+ np .testing .assert_allclose (xfm ._field , mapped_image )
193
+
194
+
123
195
124
196
@pytest .mark .parametrize ("is_deltas" , [True , False ])
125
197
def test_densefield_oob_resampling (is_deltas ):
0 commit comments