I have a (3, 2, 2) array whose three 2D subarrays I want to rotate without loops by 0°, 90°, and 180°, respectively:
import numpy as np
import matplotlib.pyplot as plt
arr = np.array([[[2,3],
[3,3]],
[[4,5],
[5,5]],
[[6,7],
[7,7]]])
for k in np.arange(3):
plt.imshow(arr[k,:,:], cmap='gray', vmin=2, vmax=7)
plt.show()
Therefore, I defined two (3, 2, 2) arrays containing the x and y indices...
x_ = np.array([[[0,1],
[0,1]],
[[0,1],
[0,1]],
[[0,1],
[0,1]]])
y_ = np.array([[[0,0],
[1,1]],
[[0,0],
[1,1]],
[[0,0],
[1,1]]])
... and rotated them:
x_rot = np.array([[[0,1],
[0,1]],
[[1,1],
[0,0]],
[[1,0],
[1,0]]])
y_rot = np.array([[[0,0],
[1,1]],
[[0,1],
[0,1]],
[[1,1],
[0,0]]])
But I don't understand why the following index assignment doesn't work, because instead each 2D subarray is rotated 180°:
arr_rot = np.zeros((3, 2, 2), dtype=int)
arr_rot[:, x_, y_] = arr[:, x_rot, y_rot]
for k in np.arange(3):
plt.imshow(arr_rot[k,:,:], cmap='gray', vmin=2, vmax=7)
plt.show()
CodePudding user response:
It looks like the issue is with the indexing. When you use arr_rot[:, x_, y_] = arr[:, x_rot, y_rot], you are assigning values to the indices specified by x_ and y_ in arr_rot using the values at indices specified by x_rot and y_rot in arr.
To rotate the 2D subarrays in arr by 0°, 90°, and 180° and assign the resulting rotated subarrays to arr_rot, you can use a combination of slicing and indexing.
import numpy as np
import matplotlib.pyplot as plt
Next, we define the (3, 2, 2) array arr:
arr = np.array([[[2,3],
[3,3]],
[[4,5],
[5,5]],
[[6,7],
[7,7]]])
Then create a new (3, 2, 2) array arr_rot filled with zeros using NumPy's zeros() function:
arr_rot = np.zeros((3, 2, 2), dtype=int)
rotate the 2D subarrays in arr and assign the resulting rotated subarrays to arr_rot using a combination of slicing and indexing:
# Rotate the first 2D subarray by 0°
arr_rot[0,:,:] = arr[0,:,:]
# Rotate the second 2D subarray by 90°
arr_rot[1,:,:] = arr[1,::-1,:].T
# Rotate the third 2D subarray by 180°
arr_rot[2,:,:] = arr[2,::-1,::-1]
The for loop iterates over the three 2D subarrays in arr_rot, and the imshow() function plots each subarray in a separate window.
# Plot the rotated 2D subarrays
for k in np.arange(3):
plt.imshow(arr_rot[k,:,:], cmap='gray', vmin=2, vmax=7)
plt.show()
Whole Code :
import numpy as np
import matplotlib.pyplot as plt
arr = np.array([[[2,3],
[3,3]],
[[4,5],
[5,5]],
[[6,7],
[7,7]]])
arr_rot = np.zeros((3, 2, 2), dtype=int)
# Rotate the first 2D subarray by 0°
arr_rot[0,:,:] = arr[0,:,:]
# Rotate the second 2D subarray by 90°
arr_rot[1,:,:] = arr[1,::-1,:].T
# Rotate the third 2D subarray by 180°
arr_rot[2,:,:] = arr[2,::-1,::-1]
# Plot the rotated 2D subarrays
for k in np.arange(3):
plt.imshow(arr_rot[k,:,:], cmap='gray', vmin=2, vmax=7)
plt.show()
CodePudding user response:
You were already really close: you can get the desired result using x_rot and y_rot by also indexing the first dimension:
out = arr[np.arange(3)[:, None, None], x_rot, y_rot]
out:
array([[[2, 3],
[3, 3]],
[[5, 5],
[4, 5]],
[[7, 7],
[7, 6]]])
CodePudding user response:
Thank you, W.A, for your detailed and understandable answer.
Sorry, I should have mentioned that I should program flexibly: arr
can be any (T, M, M) array and the T angles are given arbitrarily. So my code so far looks like this:
import numpy as np
import matplotlib.pyplot as plt
arr = np.array([[[2,3],
[3,3]],
[[4,5],
[5,5]],
[[6,7],
[7,7]]])
M = 2
T = 3
b = 2*np.pi
angles = np.array([np.linspace(0, (T-1)*b/T, T)]).T
# create indices arrays
x_ = np.tile(np.arange(M), (M, 1)).
y_ = np.tile(np.arange(M), (M, 1)).T
x_, y_ = np.repeat(x_, T, axis=0), np.tile(y_, (T, 1))
x_, y_ = x_.reshape((T, M, M)), y_.reshape((T, M, M))
# center, rotate and decenter 2D subarrays
center = -M/2 0.5
decenter = -center
x_rot = ((x_ center)*np.cos(angles) - (y_ center)*np.sin(angles)) decenter
y_rot = ((x_ center)*np.sin(angles) (y_ center)*np.cos(angles)) decenter
# set indices that lie outside 0...(M-1) equal to zero.
x_rot[(x_rot < 0) (x_rot > M-1)] = 0
y_rot[(y_rot < 0) (y_rot > M-1)] = 0
arr_rot = np.zeros((T, M, M), dtype=int)
arr_rot[:, x_, y_] = arr[:, x_rot.astype(int), y_rot.astype(int)]