8
8
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
9
9
"""Common interface for transforms."""
10
10
from collections .abc import Iterable
11
+ import numpy as np
11
12
12
13
from .base import (
13
14
TransformBase ,
@@ -74,8 +75,8 @@ def transforms(self):
74
75
@transforms .setter
75
76
def transforms (self , value ):
76
77
self ._transforms = _as_chain (value )
77
- if self .transforms [- 1 ].reference :
78
- self .reference = self .transforms [- 1 ].reference
78
+ if self .transforms [0 ].reference :
79
+ self .reference = self .transforms [0 ].reference
79
80
80
81
def append (self , x ):
81
82
"""
@@ -131,19 +132,56 @@ def map(self, x, inverse=False):
131
132
raise TransformError ("Cannot apply an empty transforms chain." )
132
133
133
134
transforms = self .transforms
134
- if not inverse :
135
- transforms = self .transforms [:: - 1 ]
135
+ if inverse :
136
+ transforms = list ( reversed ( self .transforms ))
136
137
137
138
for xfm in transforms :
138
- x = xfm (x , inverse = inverse )
139
+ x = xfm . map (x , inverse = inverse )
139
140
140
141
return x
141
142
142
- def asaffine (self ):
143
- """Combine a succession of linear transforms into one."""
144
- retval = self .transforms [- 1 ]
145
- for xfm in self .transforms [:- 1 ][::- 1 ]:
146
- retval @= xfm
143
+ def asaffine (self , indices = None ):
144
+ """
145
+ Combine a succession of linear transforms into one.
146
+
147
+ Example
148
+ ------
149
+ >>> chain = TransformChain(transforms=[
150
+ ... Affine.from_matvec(vec=(2, -10, 3)),
151
+ ... Affine.from_matvec(vec=(-2, 10, -3)),
152
+ ... ])
153
+ >>> chain.asaffine()
154
+ array([[1., 0., 0., 0.],
155
+ [0., 1., 0., 0.],
156
+ [0., 0., 1., 0.],
157
+ [0., 0., 0., 1.]])
158
+
159
+ >>> chain = TransformChain(transforms=[
160
+ ... Affine.from_matvec(vec=(1, 2, 3)),
161
+ ... Affine.from_matvec(mat=[[0, 1, 0], [0, 0, 1], [1, 0, 0]]),
162
+ ... ])
163
+ >>> chain.asaffine()
164
+ array([[0., 1., 0., 2.],
165
+ [0., 0., 1., 3.],
166
+ [1., 0., 0., 1.],
167
+ [0., 0., 0., 1.]])
168
+
169
+ >>> np.allclose(
170
+ ... chain.map((4, -2, 1)),
171
+ ... chain.asaffine().map((4, -2, 1)),
172
+ ... )
173
+ True
174
+
175
+ Parameters
176
+ ----------
177
+ indices : :obj:`numpy.array_like`
178
+ The indices of the values to extract.
179
+
180
+ """
181
+ affines = self .transforms if indices is None else np .take (self .transforms , indices )
182
+ retval = affines [0 ]
183
+ for xfm in affines [1 :]:
184
+ retval = xfm @ retval
147
185
return retval
148
186
149
187
@classmethod
@@ -157,9 +195,9 @@ def from_filename(cls, filename, fmt="X5", reference=None, moving=None):
157
195
xforms = itk .ITKCompositeH5 .from_filename (filename )
158
196
for xfmobj in xforms :
159
197
if isinstance (xfmobj , itk .ITKLinearTransform ):
160
- retval .append ( Affine (xfmobj .to_ras (), reference = reference ))
198
+ retval .insert ( 0 , Affine (xfmobj .to_ras (), reference = reference ))
161
199
else :
162
- retval .append ( DisplacementsFieldTransform (xfmobj ))
200
+ retval .insert ( 0 , DisplacementsFieldTransform (xfmobj ))
163
201
164
202
return TransformChain (retval )
165
203
0 commit comments