26
26
class DenseFieldTransform (TransformBase ):
27
27
"""Represents dense field (voxel-wise) transforms."""
28
28
29
- __slots__ = ("_field" , "_displacements " )
29
+ __slots__ = ("_field" , "_deltas " )
30
30
31
- def __init__ (self , field = None , displacements = True , reference = None ):
31
+ def __init__ (self , field = None , is_deltas = True , reference = None ):
32
32
"""
33
33
Create a dense field transform.
34
34
@@ -38,6 +38,17 @@ def __init__(self, field=None, displacements=True, reference=None):
38
38
than displacements fields.
39
39
SPM generally prefers deformations for that reason.
40
40
41
+ Parameters
42
+ ----------
43
+ field : :obj:`numpy.array_like` or :obj:`nibabel.SpatialImage`
44
+ The field of deformations or displacements (*deltas*). If given as a data array,
45
+ then the reference **must** be given.
46
+ is_deltas : :obj:`bool`
47
+ Whether this is a displacements (deltas) field (default), or deformations.
48
+ reference : :obj:`ImageGrid`
49
+ Defines the domain of the transform. If not provided, the domain is defined from
50
+ the ``field`` input.
51
+
41
52
Example
42
53
-------
43
54
>>> DenseFieldTransform(test_dir / "someones_displacement_field.nii.gz")
@@ -56,7 +67,7 @@ def __init__(self, field=None, displacements=True, reference=None):
56
67
)
57
68
else :
58
69
self ._field = np .zeros ((* reference .shape , reference .ndim ), dtype = "float32" )
59
- displacements = True
70
+ is_deltas = True
60
71
61
72
try :
62
73
self .reference = ImageGrid (
@@ -72,14 +83,14 @@ def __init__(self, field=None, displacements=True, reference=None):
72
83
ndim = self ._field .ndim - 1
73
84
if self ._field .shape [- 1 ] != ndim :
74
85
raise TransformError (
75
- "The number of components of the displacements (%d) does not match "
86
+ "The number of components of the field (%d) does not match "
76
87
"the number of dimensions (%d)" % (self ._field .shape [- 1 ], ndim )
77
88
)
78
89
79
- if displacements :
80
- self ._displacements = self ._field
81
- # Convert from displacements to deformations fields
82
- # (just add the origin to the displacements vector)
90
+ if is_deltas :
91
+ self ._deltas = self ._field
92
+ # Convert from displacements (deltas) to deformations fields
93
+ # (just add its origin to each delta vector)
83
94
self ._field += self .reference .ndcoords .T .reshape (self ._field .shape )
84
95
85
96
def __repr__ (self ):
@@ -91,29 +102,29 @@ def map(self, x, inverse=False):
91
102
Apply the transformation to a list of physical coordinate points.
92
103
93
104
.. math::
94
- \mathbf{y} = \mathbf{x} + D (\mathbf{x}),
105
+ \mathbf{y} = \mathbf{x} + \Delta (\mathbf{x}),
95
106
\label{eq:2}\tag{2}
96
107
97
- where :math:`D (\mathbf{x})` is the value of the discrete field of displacements
98
- :math:`D ` interpolated at the location :math:`\mathbf{x}`.
108
+ where :math:`\Delta (\mathbf{x})` is the value of the discrete field of displacements
109
+ :math:`\Delta ` interpolated at the location :math:`\mathbf{x}`.
99
110
100
111
Parameters
101
112
----------
102
- x : N x D numpy.ndarray
113
+ x : N x D :obj:` numpy.array_like`
103
114
Input RAS+ coordinates (i.e., physical coordinates).
104
- inverse : bool
115
+ inverse : :obj:` bool`
105
116
If ``True``, apply the inverse transform :math:`x = f^{-1}(y)`.
106
117
107
118
Returns
108
119
-------
109
- y : N x D numpy.ndarray
120
+ y : N x D :obj:` numpy.array_like`
110
121
Transformed (mapped) RAS+ coordinates (i.e., physical coordinates).
111
122
112
123
Examples
113
124
--------
114
125
>>> xfm = DenseFieldTransform(
115
126
... test_dir / "someones_displacement_field.nii.gz",
116
- ... displacements =False,
127
+ ... is_deltas =False,
117
128
... )
118
129
>>> xfm.map([-6.5, -36., -19.5]).tolist()
119
130
[[0.0, -0.47516798973083496, 0.0]]
@@ -123,7 +134,7 @@ def map(self, x, inverse=False):
123
134
124
135
>>> xfm = DenseFieldTransform(
125
136
... test_dir / "someones_displacement_field.nii.gz",
126
- ... displacements =True,
137
+ ... is_deltas =True,
127
138
... )
128
139
>>> xfm.map([[-6.5, -36., -19.5], [-1., -41.5, -11.25]]).tolist()
129
140
[[-6.5, -36.47516632080078, -19.5], [-1.0, -42.03835678100586, -11.25]]
@@ -135,7 +146,7 @@ def map(self, x, inverse=False):
135
146
ijk = self .reference .index (x )
136
147
indexes = np .round (ijk ).astype ("int" )
137
148
if np .any (np .abs (ijk - indexes ) > 0.05 ):
138
- warnings .warn ("Some coordinates are off-grid of the displacements field." )
149
+ warnings .warn ("Some coordinates are off-grid of the field." )
139
150
indexes = tuple (tuple (i ) for i in indexes .T )
140
151
return self ._field [indexes ]
141
152
@@ -147,7 +158,7 @@ def __matmul__(self, b):
147
158
--------
148
159
>>> deff = DenseFieldTransform(
149
160
... test_dir / "someones_displacement_field.nii.gz",
150
- ... displacements =False,
161
+ ... is_deltas =False,
151
162
... )
152
163
>>> deff2 = deff @ TransformBase()
153
164
>>> deff == deff2
@@ -162,7 +173,7 @@ def __matmul__(self, b):
162
173
retval = b .map (
163
174
self ._field .reshape ((- 1 , self ._field .shape [- 1 ]))
164
175
).reshape (self ._field .shape )
165
- return DenseFieldTransform (retval , displacements = False , reference = self .reference )
176
+ return DenseFieldTransform (retval , is_deltas = False , reference = self .reference )
166
177
167
178
def __eq__ (self , other ):
168
179
"""
0 commit comments