@@ -89,50 +89,6 @@ def io_orientation(affine, tol=None):
8989 return ornt
9090
9191
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-
13692def apply_orientation (arr , ornt ):
13793 ''' Apply transformations implied by `ornt` to the first
13894 n axes of the array `arr`
@@ -176,7 +132,7 @@ def apply_orientation(arr, ornt):
176132
177133
178134def orientation_affine (ornt , shape ):
179- ''' Affine transform resulting from transforms implied in `ornt`
135+ ''' Affine transform reversing transforms implied in `ornt`
180136
181137 Imagine you have an array ``arr`` of shape `shape`, and you apply the
182138 transforms implied by `ornt` (more below), to get ``tarr``.
@@ -186,38 +142,47 @@ def orientation_affine(ornt, shape):
186142
187143 Parameters
188144 ----------
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
199154 shape of array you may transform with `ornt`
200155
201156 Returns
202157 -------
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
208170 '''
209171 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 ]
212176 # ornt implies a flip, followed by a transpose. We need the affine
213177 # that inverts these. Thus we need the affine that first undoes the
214178 # effect of the transpose, then undoes the effects of the flip.
215179 # 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 ], :]
218183 undo_flip = np .diag (list (ornt [:, 1 ]) + [1.0 ])
219184 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
221186 return np .dot (undo_flip , undo_reorder )
222187
223188
0 commit comments