Ok, I am no an expert in numpy, so sorry if the answer is obvious, but this has been bugging me off for a few days now, so I have no other option than asking here. So, here is the input array I have:
a = np.array([
[0, 0, 1, 3, 4, 5, 12, 0, 0, 0, 0, 0 ],
[0, 0, 4, 0, 13, 0, 0, 2, 0, 0, 0, 0 ],
[1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0 ],
[5, 4, 9, 0, 3, 0, 7, 2, 0, 0, 0, 0 ],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[0, 0, 0, 0, 1, 0, 5, 7, 5, 0, 1, 0 ],
[0, 0, 0, 0, 0, 5, 12, 3, 0, 4, 12, 3 ],
[0, 0, 0, 0, 5, 14, 0, 9, 10, 2, 0, 15 ]
])
It needs to be split into tiles with a size of 4x4 (which means 16 elements per tile, you'll see why this is important).
I tile it up (using Iosif Doundoulakis's np.reshape()
method, explained here, big shoutout):
def tiling(arr):
# 16 - total number of elements getting into a tile
# 4 - width of a tile
# 4 - height of a tile
b = arr.reshape(arr.shape[0] // 4, 4, arr.shape[1] // 4, 4, 1)
return b.swapaxes(1, 2)
... and, when I call tiles = tiling(a)
, I get a similar result:
*I've formatted the output for easier reading, the actual output looks different, but it is organised the same way.
[[
[
[[ 0] [ 0] [ 1] [ 3]]
[[ 0] [ 0] [ 4] [ 0]]
[[ 1] [ 2] [ 3] [ 4]]
[[ 5] [ 4] [ 9] [ 0]]
]
.... this is one tile, there are 5 more ...
]]
which is exactly what I want my tiles to look like. Then, I flatten the tiled array, so it becomes
[ 0 0 1 3 0 0 4 0 1 2 3 4 5 4 9 0 4 5 12 0 13 0 0 2
5 6 7 8 3 0 7 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 5 7
0 5 12 3 5 14 0 9 0 0 0 0 5 0 1 0 0 4 12 3 10 2 0 15]
and every 16 numbers represent a tile. The next step is to pass the flatten array to an external program which returns an array with the same shape - 1 dimensional array. For now, the data is only passed to the external utility and returned by it, so the array keeps it's values.
Knowing the total number of array elements that go into a tile (16), as well as the shape of a tile (4, 4), how can I turn this 1-D array back into tiles and then create a 2-D array from those tiles, which looks like the one from the beginning?
EDIT: I was out for a few days, sorry for the delay! The thing is that I have a flat 1-D array as a result of the external utility which I want to reshape into a form, I get from the original array, so something like:
arr (with a shape (8, 12, 1))
|
| tile the array (using Iosif
| Doundoulakis's method)
V
tiled_arr = arr.reshape(2, 3, 4, 4, 1)
|
| flatten the tiled array
V
tiled_arr.flatten('C')
|
| pass to the external utility
V
it returns the same flat array, for now, but it wouldn't in the nearest future, so reformatting tiled_array is not an option
|
| pass it to a reshaping function in question
V
It should reshape the flat array back into (8, 12, 1), which is the shape of the original array arr
I came up with this code yesterday:
def reshape(flat_array, original_array):
a = np.array([np.split(flat_array, 16)]).reshape(original_array.shape[1] // 4, 4, original_array.shape[0] // 4, 4, original_array.shape[2])
b = a.reshape(2, 3, 4, 4)
return b.swapaxes(1, 2).reshape(original_array.shape)
... and it works, I get the result I want to. But it seems to me, it could be at least optimised a little bit.