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(<axes_names>) 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

Reply via email to