Thanks for your replies.
In retrospect, I realise that using the shape will not be helpful for a cubic
array i.e. the permutations of (10, 10, 10) are all (10, 10, 10)! However, the
problem remains. Let me try to explain.
Short version
The problem boils down to the meaning of axis indices as arguments to swapaxes
and transpose (and any related functions). Swapping axes or transposing an
array gives new meanings to the indices. For example, suppose I have a volume
of shape C, R, S. Then 0 will refer to C, 1 will refer to R and 2 will refer to
S. After I transpose it, say using (1, 2, 0) so that the shape becomes R, S, C
then now 0 will refer to R, 1 will refer to S and 2 will refer to C. I can no
longer reverse the transposition or transpose it predictably to achieve a
certain shape, which is an important operation in some applications where the
meaning of the axes is significant.
Long version
Suppose I have a volume of shape (C, R, S) and I have a corresponding
assignment of physical axes so that C=X, R=Y and S=Z. This is equivalent to
placing the volume with C along the X axis, R along Y axis and S along the Z
axis. Now, suppose I would like to permute the axes by only making reference to
the axis names: what is the shape corresponding to the orientation (Z, Y, X)?
This is a simple example because we only swap two axes and the resulting shape
is the same as performing the same swap in the shape: (S, R, C). If we knew the
indices of the axis names then we can infer these and pass them to swapaxes or
transpose:
vol = numpy.random.rand(C, R, S) # of shape (C, R, S) -> (X, Y, Z)
# now (Z, Y, X)
new_vol = numpy.swapaxes(vol, 0, 2)
new_vol.shape # (S, R, C)
The same applies to a double swap e.g. (Y, Z, X), though it is less
straightforward using swapaxes. swapaxes only takes two indices (obviously) so
we would need to call it twice reflecting the two swaps required. So we have to
somehow figure which axes to swap successively: ((0, 2) then (0, 1)). We can do
this in one step with numpy.transpose simply using indices (1, 2, 0).
However, (and this is the big 'however'), how would we reverse this? The array
has no memory of the original axes and 0, 1, and 2 now refer to the current
axes. This is where the axes names (e.g. X, Y and Z) would come in handy.
Axis names will allow permutations to happen predictably since the array will
'remember' what the original references were.
Here is what I propose: an API to numpy.ndarray with some identity e.g.
vol = numpy.random.rand(C, R, S)
vol.shape # C, R, S
vol.axes = ('X', 'Y', 'Z') # C=X, R=Y, S=Z
new_vol = vol.permute_axes(('Z', 'Y', 'X'))
# either
new_vol.axes # ('X', 'Y', 'Z') # preserve orientation but change shape
new_vol.shape # S, R, C
# or
new_vol.axes # ('Z', 'Y', 'X') # preserve shape but change orientation
new_vol.shape # C, R, S
# we can now reverse the permutation
old_vol = new_vol.permute_axes(('X', 'Y', 'Z'))
numpy.array_equal(vol, old_vol) # True
I've checked the numpy API documentation and there is no attribute .axes
present so this is the best candidate. Additionally, this will require the
.permute_axes() method/function.
Thanks for your consideration.
Paul
___
NumPy-Discussion mailing list -- numpy-discussion@python.org
To unsubscribe send an email to numpy-discussion-le...@python.org
https://mail.python.org/mailman3/lists/numpy-discussion.python.org/
Member address: arch...@mail-archive.com