Numpy concatenate behaviour. How to concatenate example correctly - python

I have following multi-dimensional array:
windows = array([[[[[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]],
[[0., 0.],
[1., 0.]]],
[[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[1., 0.],
[0., 0.]]],
[[[1., 0.],
[0., 0.]],
[[0., 1.],
[0., 0.]],
[[0., 1.],
[0., 0.]]]]]])
print(windows.shape)
(1, 1, 3, 3, 2, 2) # (n, d, a, b, c, c) w = a * (c*c), h = b * (c*c)
I want to get next resulting array:
mask = array([[
[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]
]], dtype=np.float32)
print(mask.shape)
(1, 1, 6, 6) # (n, d, w, h)
Basically, I want to squeeze last 4 dimensions into 2-d matrix so the final shape become (n, d, w, h), in this case (1, 1, 6, 6).
I tried np.concatenate(windows, axis = 2), but it didnt concatenate along 2nd dimension and reduced for some reason first(although I set axis = 2) 'n' dimension.
Additional information:
windows is a result of following code snippet
windows = np.lib.stride_tricks.sliding_window_view(arr, (c, c), axis (-2,-1), writeable = True) # arr.shape == mask.shape
windows = windows[:, :, ::c, ::c] # these are non-overlapping windows of arr with size (c,c)
windows = ... # some modifications of windows
Now I want to build from these windows array with shape of arr.shape, this array called mask in example above. Simple reshape doesn't work because it returns elements in wrong order.

IIUC, you want to merge dimensions 2+4 and 3+5, an easy way would be to swapaxes 4 and 5 (or -3 and -2), and reshape to (1,1,6,6):
windows.swapaxes(-2,-3).reshape(1,1,6,6)
output:
array([[[[0., 0., 0., 0., 0., 0.],
[1., 0., 1., 0., 1., 0.],
[0., 1., 0., 1., 1., 0.],
[0., 0., 0., 0., 0., 0.],
[1., 0., 0., 1., 0., 1.],
[0., 0., 0., 0., 0., 0.]]]])

Related

Making a 3D diagonal matrix in Python

I would like to create 3D diagonal matrices. I already succeded to create one with numpy routine numpy.fill_diagonal(numpy.zeros((N, N, N)), n), however it does not allow to choose the diagonal to fill.
In other words, I would like to find the 3D generalization of this numpy routine : https://numpy.org/doc/stable/reference/generated/numpy.diag.html. Thank you.
Well instead of using np.diag to fill a semi diagonal you can do it manually like this:
N = 4
arr = np.zeros((N, N))
i = np.arange(N-1)
arr[i,i+1] = 1
array([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]])
And it has the advantage to generalize to 3d arrays.
arr = np.zeros((N, N, N))
i = np.arange(N-1)
arr[i,i,i+1] = 1
array([[[0., 1., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]],
[[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]]])

Numpy - set first max value over multiple axes

I have a multidimensional array with the last two dimensions corresponding a "window". For each "window" in the array my goal is to set the first max value in the window to 1 and the rest of the values to 0. For example, for one window, we have this assignment:
[[0., 0., 0.], [[0., 0., 0.],
[0., 1., 1.], -> [0., 1., 0.],
[0., 1., 1.]], [0., 0., 0.]]
Now, i want to do this for all windows, where each window is on the last two dimensions, i.e. axis=(-1,-2). This is what I have tried so far:
# windows
x = np.array([[[[[[0., 0., 0.],
[0., 1., 1.],
[0., 1., 1.]],
[[0., 0., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 1.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 1., 0.]]],
[[[0., 1., 1.],
[0., 1., 1.],
[0., 1., 0.]],
[[1., 1., 0.],
[1., 1., 0.],
[1., 0., 1.]]]]]])
max_indices = np.argwhere(x == x.max()) # all indicies of max values in x
mask = np.zeros_like(x) # start of with everything set to 0
# I can set the first window by doing the following
mask[tuple(max_indices[0])] = 1.0
How can i do the same for all other windows? Preferably without looping.
My idea was to find unique values in max_indices where the last two dimensions are not taken into account, but i am not sure how to go about this.
EDIT
I have a case where x in the scenario above is taken from another
array using np.lib.stride_tricks.as_strided, which means that the strides will differ.
Here is the case:
# The image or whatever i want to modify
x = np.array([[[[0., 0., 0., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 1., 0.],
[0., 1., 0., 1.]]]])
# the windows of that image
x = np.lib.stride_tricks.as_strided(x, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))
Using the solution given by Felipe:
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
# plug it back
x[0][0] = y
x
array([[[[[[0., 0., 0.],
[0., 1., 0.],
[0., 1., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[1., 0., 0.]]],
[[[0., 1., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]]]])
The shape is the same but with different strides in x and y it seems as if "plugging it back" causes x and y to not be identical, which I would expect.
Here's one way using np.put_along_axis (though this is really just a somewhat faster loop).
y = x[0][0] # Just unnesting it a bit
yr = y.reshape(-1, 9)
idx = yr.argmax(1)
y0 = np.zeros_like(yr)
np.put_along_axis(y0, idx[:, None], 1, axis=1)
y = y0.reshape(y.shape)
Output:
array([[[[0., 0., 0.],
[0., 1., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[1., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]],
[[[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]]]])
EDIT
Not the brightest idea but what I meant is you could reassign it first to a copy of it and then get your strided view again, something like:
x0 = x.copy() # Get a normal view
# [ Run the previous snippet ]
x0[0][0] = y # Assign the modified version
# Then if you really want another strided view you can recreate it
x0 = x0.reshape(saved_x.shape) # Reshape it to the original version pre-stride
x = np.lib.stride_tricks.as_strided(x0, shape=(1, 1, 3, 2, 3, 3), strides=(160, 160, 32, 8, 32, 8))

weird behavior of numpy when it calculates a vector and matrix multiplication

I have the following weird behavior of numpy where numpy can't multiply a (n,n) matrix with (n,) matrix and convert the later to (1,n) matrix. I tried different examples and it worked fine. u and s were obtained from svd function as follows:
[u, s, vt] = np.linalg.svd(G)
svd_estimate = np.matmul(u * s, vt)
and G is a numpy matrix. I tried to squeeze(s) but also didn't work. What am I missing? numpy version is '1.19.2'
Look at what svd produces for a matrix versus array:
In [24]: np.linalg.svd(np.matrix(np.eye(3)))
Out[24]:
(matrix([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]),
array([1., 1., 1.]),
matrix([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]))
In [25]: np.linalg.svd(np.eye(3))
Out[25]:
(array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]),
array([1., 1., 1.]),
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]]))
With the array values, as shown in the docs:
In [27]: u,s,vh=_25
In [28]: np.dot(u*s,vh)
Out[28]:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
With the matrix results we have use np.multiply
In [37]: u,s,vh=_24
In [38]: np.multiply(u,s)
Out[38]:
matrix([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
In [39]: np.multiply(u,s)*vh
Out[39]:
matrix([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])

Adding column to higher dimension

let's assume that i have array called A
A = np.zeros((4, 3, 2))
array([[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]],
[[0., 0.],
[0., 0.],
[0., 0.]]])
and another array called B
B = np.arange(4)
array([0, 1, 2, 3])
and i want to do something like concatenation in the third dimension to got this result:
array([[[0., 0., 0.0],
[0., 0., 0.0],
[0., 0., 0.0]],
[[0., 0., 1.0],
[0., 0., 1.0],
[0., 0., 1.0]],
[[0., 0., 2.0],
[0., 0., 2.0],
[0., 0., 2.0]],
[[0., 0., 3.0],
[0., 0., 3.0],
[0., 0., 3.0]]])
i tried serval ways to do that but i didn't succeed.
who i can do that in good way not loops?
To add the extra dimension you can use np.append. You just have to get the shape correct. You can use np.repeat() to make the repeating elements:
A = np.zeros((4, 3, 2))
h, w, d = A.shape
B = np.repeat(np.arange(h), w).reshape([h, w, 1])
np.append(A, B, axis=2)
Output:
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])
We could broadcast B to the corresponding shape and use advanced indexing here and assign B broadcasted across the corresponding axes:
np.concatenate([A, np.broadcast_to(B[:,None,None], A[...,-1:].shape)], -1)
print(A)
array([[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 1.],
[0., 0., 1.],
[0., 0., 1.]],
[[0., 0., 2.],
[0., 0., 2.],
[0., 0., 2.]],
[[0., 0., 3.],
[0., 0., 3.],
[0., 0., 3.]]])

Is it possible to Copy Subregion of One 2D Array to Another Using numpy.ndarray

I have some 2d arrays using numpy, and I want to copy subregions from one into another. For example, if I start with:
dest = numpy.zeros((4, 4))
# array([[0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.],
# [0., 0., 0., 0.]])
src = numpy.ones((4, 4))
# array([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])
I want to somehow say that the src should be copied into dest at (2,1), such that source would then look like:
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Or if (-3, 0), then:
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])
I can do the good old fashioned double index loop to do this, but I was hoping numpy had some clever magic that did it. I looked at take, but couldn't see how to make that the tool for this job.
Both of these can be accomplished with numpy indexing. To understand how this works, the documentation is always your friend.
Your first case:
dest[1: ,2:] = src[1: ,2:]
array([[0., 0., 0., 0.],
[0., 0., 1., 1.],
[0., 0., 1., 1.],
[0., 0., 1., 1.]])
Your second case: (You indicated column -3 but your results indicate -4)
dest[:, -4] = src[:, -4]
array([[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.],
[1., 0., 0., 0.]])

Categories

Resources