Move 3D array values, knowing new coordinates with mask

I would like to expand on the problem that I have already talked about in https://stackoverflow.com/a/2129609/169 . It dealt with numpy 2D arrays, and I would like to do the same with a 3-dimensional array.

I would like to "move" the elements of a 2D array to the new coordinates, which are stored in two other arrays. I want to automate this because my arrays are actually large (400x200x100). Some values ​​will not find its coordinates and will not be used. Some of these coordinates are masked, which I indicated in the example below using the value 0. If the coordinate is masked, the elements in the array that I want to rearrange will not.

import numpy as np #My new coordinates in X and Y directions mx = np.array([[[ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.]], [[ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.], [ 1., 2., 3., 4., 0.]]]) my = np.array([[[ 0., 2., 2., 2., 2.], [ 0., 3., 3., 3., 3.], [ 0., 4., 4., 4., 4.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]], [[ 0., 2., 2., 2., 2.], [ 0., 3., 3., 3., 3.], [ 0., 4., 4., 4., 4.], [ 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0.]]]) IRtest = np.array([[[-0.07383495, -0.08606554, -0.08480594, -0.08099556, -0.08218414], [-0.07866761, -0.08373 , -0.08253587, -0.08106102, -0.08220205], [-0.07727436, -0.08271511, -0.0807254 , -0.07832416, -0.08021686], [-0.07612349, -0.08190446, -0.07996929, -0.07842754, -0.08024891], [-0.07488144, -0.08150557, -0.08038229, -0.07895656, -0.07997815]], [[-0.07383495, -0.08606554, -0.08480594, -0.08099556, -0.08218414], [-0.07866761, -0.08373 , -0.08253587, -0.08106102, -0.08220205], [-0.07727436, -0.08271511, -0.0807254 , -0.07832416, -0.08021686], [-0.07612349, -0.08190446, -0.07996929, -0.07842754, -0.08024891], [-0.07488144, -0.08150557, -0.08038229, -0.07895656, -0.07997815]]]) 

So, the expected array looks like this:

 array_expected = np.array([[[-0.08271511, -0.0807254 , -0.07832416, -0.08021686, 0], [-0.08190446, -0.07996929, -0.07842754, -0.08024891, 0], [-0.08150557, -0.08038229, -0.07895656, -0.07997815, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]], [[-0.08271511, -0.0807254 , -0.07832416, -0.08021686, 0], [-0.08190446, -0.07996929, -0.07842754, -0.08024891, 0], [-0.08150557, -0.08038229, -0.07895656, -0.07997815, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]]) 

I am trying the piece of code that I received with the last message.

 b = np.zeros_like(IRtest) for i in range(IRtest.shape[1]): for j in range(IRtest.shape[2]): for k in range(IRtest.shape[0]): b[k, j, i] = IRtest[k,my[k,j,i],mx[k,j,i]]*(mx[k,j,i]!=-1)*(my[k,j,i]!=-1) b 

But the result is not what I expected:

  array([[[-0.08606554, -0.0807254 , -0.07832416, -0.08021686, -0.07727436], [-0.08606554, -0.07996929, -0.07842754, -0.08024891, -0.07612349], [-0.08606554, -0.08038229, -0.07895656, -0.07997815, -0.07488144], [-0.08606554, -0.08480594, -0.08099556, -0.08218414, -0.07383495], [-0.08606554, -0.08480594, -0.08099556, -0.08218414, -0.07383495]], [[-0.08606554, -0.0807254 , -0.07832416, -0.08021686, -0.07727436], [-0.08606554, -0.07996929, -0.07842754, -0.08024891, -0.07612349], [-0.08606554, -0.08038229, -0.07895656, -0.07997815, -0.07488144], [-0.08606554, -0.08480594, -0.08099556, -0.08218414, -0.07383495], [-0.08606554, -0.08480594, -0.08099556, -0.08218414, -0.07383495]]]) 
+6
source share
2 answers

The matrices of your card are wrong to get the result you need so that they look like them (because when you put the values ​​in b, you check if m [k, j, i]! = -1 and you want the last columns are 0, not the first)

 mx = np.array([[[ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.]], [[ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.], [ 1., 2., 3., 4., -1.]]]) my = np.array([[[ 2., 2., 2., 2., -1.], [ 3., 3., 3., 3., -1.], [ 4., 4., 4., 4., -1.], [ -1., -1., -1., -1., -1.], [ -1., -1., -1., -1., -1.]], [[ 2., 2., 2., 2., -1.], [ 3., 3., 3., 3., -1.], [ 4., 4., 4., 4., -1.], [ -1., -1., -1., -1., -1.], [ -1., -1., -1., -1., -1.]]]) 

Also in your cycles it would be better to switch sizes in the first and second cycles so that they become

 for i in range(IRtest.shape[2]): for j in range(IRtest.shape[1]): for k in range(IRtest.shape[0]): 

It doesn’t matter for the case that you present here, because the matrices are square, but the real problem you are talking about is not square, so it becomes a problem.

+4
source

To summarize the answer to your previous question regarding 2dim, you can simply use fancy indexing (for example, after fixing the types of your arrays):

 b = IRtest[my,mx] * ~(mask_my | mask_mx) 

Now, to apply the same method to the 3dim case, you need to create a “neutral” index array applicable to the first axis. Here np.indices is useful:

 mz = np.indices(IRtest.shape)[0] # take [0] because we need to be neutral wrt axis=0 

Now apply fantastic indexing:

 b = IRtest[mz, my, mx] 

To apply a mask, it is easiest to add a dimension to the mask array to make it 3dim, then let the numpy cast do its magic. (I assume that we are using the same masks from the 2dim question, with dtype = bool).

 unified_mask = mask_my | mask_mx b *= ~unified_mask[np.newaxis,...] 

As with 2dim, you could use a fancy assignment (again, axis translation = 0):

 b[unified_mask[np.newaxis,...]] = 0. 
+1
source

Source: https://habr.com/ru/post/978608/


All Articles