Unravel 1D list back to 3D array - python

Basically, is there a way to transform a 1D list that has been "flattened" through the numpy.ravel() function back to it's original 3D form ? I know the dimensions, and one might ask why I just don't use the original 3D array in the first place, instead of converting it - but there reasons for that.
I just need to know if I can actually create the same 3D array from a 1D array that was created by using numpy.ravel() on the 3D array.
Basically the 3D array was created like this:
import numpy as np
nx = 50
ny = 40
nz = 150
x = np.linspace(1, 51, nx)
y = np.linspace(1, 41, ny)
z = np.linspace(1, 151, nz)
x_bc = x[:, np.newaxis, np.newaxis]
y_bc = y[np.newaxis, :, np.newaxis]
z_bc = z[np.newaxis, np.newaxis, :]
arr = x_bc + y_bc + z_bc
And nope, I can't just do this to get it back, since calculations has been done to it in the mean time, and then converted to a 1D array in the mean time as well. So the data in this array is not the same as the one I actually want to convert back.

Just reshape it back to the original shape?
raveled = np.ravel(arr)
new_arr = raveled.reshape(*arr.shape)

Does numpy.reshape do what you want?

Related

4D array into 2D array and again back to 4D

I have the poses of humans (X, Y, Z values of joints like left elbow, right knee etc) in a video saved in a 4D numpy array.
Example: The poses are saved in the array of shape 3, 103, 25, 2 means:
3(number of Co-ordinates), 103(number of Frames), 25(Number of Joints), 2(number of persons).
Now I want to change the view angle of this observation. i.e. I want to apply a rotation matrix on all the joint position values.
As of now, I'm
iterating through the number of persons
converting each person into 2-D array
Multiplying the 2D array with a rotation 3x3 matrix
Reshaping the rotated 2D array into 3D array
Appending the 3D arrays
seq = np.random.rand(3, 103, 25, 2)
rot_mat = np.random.rand(3,3)
rotated_seq = np.zeros(seq.shape)
for i in range(seq.shape[3]): # iterating through person
person = seq[:, :, :, i]
joint_values = np.reshape(person, (3, -1))
rotated_joint_values = np.dot(joint_values.T, rot_mat).T
rotated_person = np.reshape(rotated_joint_values, person.shape)
rotated_seq[:, :, :, i] = rotated_person
My question is there any way to do this without using the for loop.

Attach matrix to inside of matrix in numpy

Suppose there are 4D matrix (3,4,6,1) and 2D array (6,4) , I want to attach the 2D array left side of 2D matrix[0:3][0:4].
I can only do this problem using for loop.
for i in range(0, cols):
for j in range(0, rows):
x = np.append(a[i][j], b, axis = 1)
I try to make 2D -> 4D and use np.append ,but still don't know how to make 2D-> 4D like (3,4,6,4).
If I understand your requirements correctly one simple way would be
out = np.empty((3, 4, 6, 5))
out[..., :1] = a
out[..., 1:] = b

Slice subarray from numpy array by list of indices

I have a 2D numpy array input_array and two lists of indices (x_coords and y_coords). Id like to slice a 3x3 subarray for each x,y pair centered around the x,y coordinates. The end result will be an array of 3x3 subarrays where the number of subarrays is equal to the number of coordinate pairs I have.
Preferably by avoiding for loops. Currently I use a modification of game of life strides from the scipy cookbook:
http://wiki.scipy.org/Cookbook/GameOfLifeStrides
shape = (input_array.shape[0] - 2, input_array.shape[0] - 2, 3, 3)
strides = input_array.strides + input_array.strides
strided = np.lib.stride_trics.as_strided(input_array, shape=shape, strides=strides).\
reshape(shape[0]*shape[1], shape[2], shape[3])
This creates a view of the original array as a (flattened) array of all possible 3x3 subarrays. I then convert the x,y coordinate pairs to be able to select the subarrays I want from strided:
coords = x_coords - 1 + (y_coords - 1)*shape[1]
sub_arrays = strided[coords]
Although this works perfectly fine, I do feel it is a bit cumbersome. Is there a more direct approach to do this? Also, in the future I would like to extend this to the 3D case; slicing nx3x3 subarrays from a nxmxk array. It might also be possible using strides but so far I haven't been able to make it work in 3D
Here is a method that use array broadcast:
x = np.random.randint(1, 63, 10)
y = np.random.randint(1, 63, 10)
dy, dx = [grid.astype(int) for grid in np.mgrid[-1:1:3j, -1:1:3j]]
Y = dy[None, :, :] + y[:, None, None]
X = dx[None, :, :] + x[:, None, None]
then you can use a[Y, X] to select blocks from a. Here is an example code:
img = np.zeros((64, 64))
img[Y, X] = 1
Here is graph ploted by pyplot.imshow():
A very straight forward solution would be a list comprehension and itertools.product:
import itertools
sub_arrays = [input_array[x-1:x+2, y-1:y+2]
for x, y in itertools.product(x_coords, y_coords)]
This creates all possible tuples of coordinates and then slices the 3x3 arrays from the input_array.
But this is sort-of a for loop. And you will have to take care, that x_coords and y_coords are not on the border of the matrix.

Python 3d array times 1d vector

I'm trying to multiply a [12x256x256] array with a [12] array. The idea is taht the first one is a stack of 12 [256x256] arrays and the 2nd one is a stack of 1d scalars. So if the 2nd array is [1,2,3,4,...,12], then I want to multiply the first layer of the 3d one by 1, the 2nd layer by 2, etc.
How can I do this?
You can add new axises and multiply them.
import numpy as np
a = np.ones((12,256,256))
b = np.array(range(12))+1
c = a * b[:, np.newaxis, np.newaxis]
In numpy you can do
# let m be 12x256x256, n be 12
m = np.array(m)
n = np.array(n)
(m.swapaxes(0,2) * n).swapaxes(2,0)

numpy.concatenate multidimensional arrays

I'm searching for an algorithm to merge a given number of multidimensional arrays (each of the same shape) to a given proportion (x,y,z).
For example 4 arrays with the shape (128,128,128) and the proportion (1,1,4) to an array of the shape (128,128,512).
Or 2 arrays with the shape (64,64,64) and the proportion (1,2,1) to an array of the shape (64,128,64)
I know how to do it manually with np.concatenate, but I need a general algorithm to do this. (np.reshape doesn't work - this will mess up the order)
edit: It's possible that the proportion is (1,2,3), then it is necessary to compare the left_edge of the box, to know where to place it. every array have a corresponding block with the attribute left_edge (xmin, ymin, zmin). Can I solve this with a if-condition?
If your proportion is always one-dimensional (i.e. concatenate in one dimension only), you can use this:
arrays = [...]
proportion = (1,1,4)
np.concatenate(arrays, axis=next(i for i,p in enumerate(proportion) if p>1))
Otherwise you have to explain what to do with proportion = (1,2,3)
Okay I programmed it this way and it seems to work. Maybe not the nicest way, but it do what I want.
blocks.sort(key=lambda x: (x.left_edge[2],x.left_edge[1],x.left_edge[0]))
proportion = (Nx * nblockx, Ny * nblocky, Nz * nblockz)
arrays = np.zeros((nblockx, nblocky, nblockz, Nx, Ny, Nz))
for block, (x,y,z) in zip(root_list,
product(range(nblockx),
range(nblocky),
range(nblockz))):
array = np.zeros((Nx, Ny, Nz), dtype = np.float64)
# this is only the function to fill the array
writearray(array, ...)
arrays[x,y,z] = array
shape = arrays.shape
array = np.zeros((shape[0]*shape[3], shape[1]*shape[4], shape[2]*shape[5]))
for x,y,z in product(range(shape[0]), range(shape[1]), range(shape[2])):
slicex = slice(x*shape[3], (x+1)*shape[3])
slicey = slice(y*shape[4], (y+1)*shape[4])
slicez = slice(z*shape[5], (z+1)*shape[5])
array[slicex, slicey, slicez] = arrays[x,y,z]
return array

Categories