@@ -89,50 +89,6 @@ def io_orientation(affine, tol=None):
89
89
return ornt
90
90
91
91
92
- def _ornt_to_affine (orientations ):
93
- ''' Create affine transformation matrix determined by orientations.
94
-
95
- This transformation will simply flip, transpose, and possibly drop some
96
- coordinates.
97
-
98
- Parameters
99
- ----------
100
- orientations : (p, 2) ndarray
101
- one row per input axis, where the first value in each row is the closest
102
- corresponding output axis. The second value in each row is 1 if the input
103
- axis is in the same direction as the corresponding output axis and -1 if
104
- it is in the opposite direction. If a row is [np.nan, np.nan], which can
105
- happen when p > q, then this row should be considered dropped.
106
-
107
- Returns
108
- -------
109
- affine : (q + 1, p + 1) ndarray
110
- matrix representing flipping / dropping axes. q is equal to the number of
111
- rows of ``orientations[:, 0]`` that are not np.nan
112
- '''
113
- ornt = np .asarray (orientations )
114
- p = ornt .shape [0 ]
115
- keep = ~ np .isnan (ornt [:, 1 ])
116
- # These are the input coordinate axes that do have a matching output
117
- # column in the orientation. That is, if the 2nd row is [np.nan,
118
- # np.nan] then the orientation indicates that no output axes of an
119
- # affine with this orientation matches the 2nd input coordinate
120
- # axis. This would happen if the 2nd row of the affine that
121
- # generated ornt was [0,0,0,*]
122
- axes_kept = np .arange (p )[keep ]
123
- q = keep .sum (0 )
124
- # the matrix P represents the affine transform impled by ornt. If
125
- # all entries of ornt are not np.nan, then P is square otherwise it
126
- # has more columns than rows indicating some coordinates were
127
- # dropped
128
- P = np .zeros ((q + 1 , p + 1 ))
129
- P [- 1 , - 1 ] = 1
130
- for idx in range (q ):
131
- axs , flip = ornt [axes_kept [idx ]]
132
- P [idx , axs ] = flip
133
- return P
134
-
135
-
136
92
def apply_orientation (arr , ornt ):
137
93
''' Apply transformations implied by `ornt` to the first
138
94
n axes of the array `arr`
@@ -176,7 +132,7 @@ def apply_orientation(arr, ornt):
176
132
177
133
178
134
def orientation_affine (ornt , shape ):
179
- ''' Affine transform resulting from transforms implied in `ornt`
135
+ ''' Affine transform reversing transforms implied in `ornt`
180
136
181
137
Imagine you have an array ``arr`` of shape `shape`, and you apply the
182
138
transforms implied by `ornt` (more below), to get ``tarr``.
@@ -186,38 +142,47 @@ def orientation_affine(ornt, shape):
186
142
187
143
Parameters
188
144
----------
189
- ornt : (n,2) ndarray
190
- orientation transform. ``ornt[N,1]` is flip of axis N of the
191
- array implied by `shape`, where 1 means no flip and -1 means
192
- flip. For example, if ``N==0`` and ``ornt[0,1] == -1``, and
193
- there's an array ``arr`` of shape `shape`, the flip would
194
- correspond to the effect of ``np.flipud(arr)``. ``ornt[:,0]`` is
195
- the transpose that needs to be done to the implied array, as in
196
- ``arr.transpose(ornt[:,0])``
197
-
198
- shape : length n sequence
145
+ ornt : (p, 2) ndarray
146
+ orientation transform. ``ornt[P, 1]` is flip of axis N of the array
147
+ implied by `shape`, where 1 means no flip and -1 means flip. For
148
+ example, if ``P==0`` and ``ornt[0, 1] == -1``, and there's an array
149
+ ``arr`` of shape `shape`, the flip would correspond to the effect of
150
+ ``np.flipud(arr)``. ``ornt[:,0]`` gives us the (reverse of the)
151
+ transpose that has been done to ``arr``. If there are any NaNs in
152
+ `ornt`, we raise an ``OrientationError`` (see notes)
153
+ shape : length p sequence
199
154
shape of array you may transform with `ornt`
200
155
201
156
Returns
202
157
-------
203
- transformed_affine : (n+1,n+1) ndarray
204
- An array ``arr`` (shape `shape`) might be transformed according
205
- to `ornt`, resulting in a transformed array ``tarr``.
206
- `transformed_affine` is the transform that takes you from array
207
- coordinates in ``tarr`` to array coordinates in ``arr``.
158
+ transformed_affine : (p + 1, p + 1) ndarray
159
+ An array ``arr`` (shape `shape`) might be transformed according to
160
+ `ornt`, resulting in a transformed array ``tarr``. `transformed_affine`
161
+ is the transform that takes you from array coordinates in ``tarr`` to
162
+ array coordinates in ``arr``.
163
+
164
+ Notes
165
+ -----
166
+ If a row in `ornt` contains NaN, this means that the input row does not
167
+ influence the output space, and is thus effectively dropped from the output
168
+ space. In that case one ``tarr`` coordinate maps to many ``arr``
169
+ coordinates, we can't invert the transform, and we raise an error
208
170
'''
209
171
ornt = np .asarray (ornt )
210
- n = ornt .shape [0 ]
211
- shape = np .array (shape )[:n ]
172
+ if np .any (np .isnan (ornt )):
173
+ raise OrientationError ("We cannot invert orientation transform" )
174
+ p = ornt .shape [0 ]
175
+ shape = np .array (shape )[:p ]
212
176
# ornt implies a flip, followed by a transpose. We need the affine
213
177
# that inverts these. Thus we need the affine that first undoes the
214
178
# effect of the transpose, then undoes the effects of the flip.
215
179
# ornt indicates the transpose that has occurred to get the current
216
- # ordering, relative to canonical, so we just use that
217
- undo_reorder = np .eye (n + 1 )[list (ornt [:, 0 ]) + [n ], :]
180
+ # ordering, relative to canonical, so we just use that.
181
+ # undo_reorder is a row permutatation matrix
182
+ undo_reorder = np .eye (p + 1 )[list (ornt [:, 0 ]) + [p ], :]
218
183
undo_flip = np .diag (list (ornt [:, 1 ]) + [1.0 ])
219
184
center_trans = - (shape - 1 ) / 2.0
220
- undo_flip [:n , n ] = (ornt [:, 1 ] * center_trans ) - center_trans
185
+ undo_flip [:p , p ] = (ornt [:, 1 ] * center_trans ) - center_trans
221
186
return np .dot (undo_flip , undo_reorder )
222
187
223
188
0 commit comments