You could easily write an extension to ndarray that maps axis names to indices and vice versa.
Joe On Tue, May 17, 2022, 21:32 Paul Korir <polaris...@gmail.com> wrote: > 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: jfoxrabinov...@gmail.com >
_______________________________________________ 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