Creating new 2D array from a slice of 3D array in python? - python

I have a 3D array [256,256,450] that I would like to fetch a 2D array from a cross section along the z axis. The new 2D array should start at z=0 at the top and have the values across some i'th y slice for x =0 to x=255. Then the next row in the new 2D array should be the same for z=1, and so on until z=449. How can this be done?

Use NumPy's NDArray class and slicing syntax.
import numpy as np
my_array = np.zeros([256, 256, 450]) # 256x256x450 array
... # Do whatever you want to do to load data in
x_slice = my_array[0,:,:] # A 256x450 array, the first element in x
y_slice = my_array[:,0,:] # A 256x450 array, the first element in y
y_slice = my_array[:,99,:] # A 256 x 450 array, the 100th element in y

import numpy as np
array_3d = np.ones((256, 256, 450))
y_layer = 24 # arbitrary y layer
array_2d = array_3d[:, y_layer, :]

Related

A 2d matrix can be reconstructed, in which a mask has been used with numpy where and flattened

As the question says I have a 2D matrix (1000, 2000), in which I apply a condition with the numpy where function, in this way:
import numpy as np
A = np.random.randn(1000, 2000)
print(A.shape)
(1000, 2000)
mask = np.where((A >=0.1) & (A <= 0.5))
A = A[mask]
print(A.shape)
(303112,)
and I get a flattened matrix which I use as input in a Fortran program which only supports 1D matrices, the output of this program has the same dimension as the input 1D matrix (303112,), is there any method or function to reconstruct the flattened matrix to its original 2D form. I was thinking of saving the indexes in a boolean matrix and use these to reconstruct the matrix, if someone knows of any numpy method or any suggestion would be of great help.
Greetings.
IIUC you need to maintain the 1D indexes and 2D indexes of the mask so that when you try to update those values using a FORTRAN program, you can switch to 1D for input and then switch back to 2D to update the original array.
You can use np.ravel_multi_index to convert 2D indexes to 1D. Then you can use these 1D indexes to convert them back to 2D using np.unravel_index (though since you already have the 2D mask, you don't need to convert 1D to 2D again.)
import numpy as np
A = np.random.randn(1000, 2000)
mask = np.where((A >=0.1) & (A <= 0.5))
idx_flat = np.ravel_multi_index(mask, (1000,2000)) #FLAT 1D indexes using original mask
idx_2d = np.unravel_index(idx_flat, (1000,2000)) #2D INDEXES using the FLAT 1D indexes
#Comparing the method of using flat indexes and A[mask]
print(np.allclose(A.ravel()[idx_flat],A[mask]))
### True
#Comparing the freshly created 2d indexes to the original mask
print(np.allclose(idx_2d,mask))
### True
Here is a dummy test case with end to end code for a (3,3) matrix.
import numpy as np
#Dummy matrix A and mask
A = np.random.randn(3, 3) #<---- shape (3,3)
mask = np.where(A <= 0.5)
mask[0].shape #Number of indexes in 2D mask
###Output: (6,)
#########################################################
#Flatten 2D indexes to 1D
idx_flat = np.ravel_multi_index(mask, (3,3)) #<--- shape (3,3)
idx_flat.shape #Number of indexes in flattened mask
###Output: (6,)
#########################################################
#Feed the 6 length array to fortran function
def fortran_function(x):
return x**2
flat_array = A.ravel()[idx_flat]
fortran_output = fortran_function(flat_array)
#Number of values in fortran_output
fortran_output.shape
###Output: (6,)
#########################################################
#Create a empty array
new_arr = np.empty((3,3)) #<---- shape (3,3)
new_arr[:] = np.nan
new_arr[mask] = fortran_output #Feed the 1D array to the 2D masked empty array
new_arr
array([[5.63399114e-04, nan, 7.86255167e-01],
[3.94992857e+00, 4.88932044e-02, 2.45489069e+00],
[3.51957270e-02, nan, nan]])

Numpy array into multidimensional slices at different indices

Given a numpy array and integer x, is there a way to create a multi-dimensional numpy array where each row is a slice of the original array starting from index 0 ... x without hard-coding? For example, if x = 3:
array = np.arange(10)
output = np.array([array, array[1:], array[2:], array[3:]])

Append numpy one dimensional arrays does not lead to a matrix

I am trying to get a 2d array, by randomly generating its rows and appending
import numpy as np
my_nums = np.array([])
for i in range(100):
x = np.random.rand(2, 1)
my_nums = np.append(my_nums, np.array(x))
But I do not get what I want but instead get a 1d array.
What is wrong?
Transposing x did not help either.
You could do this by using np.append(axis=0) or np.vstack. This however requires the rows appended to have the same length as the rows already in the array.
You cannot use the same code to append a row with two values to an empty array, and to append a row to an already existing 2D array: numpy will throw a
ValueError: all the input arrays must have same number of dimensions.
You could initialize my_nums to work around this:
my_nums = np.random.rand(1, 2)
for i in range(99):
x = np.random.rand(1, 2)
my_nums = np.append(my_nums, x, axis=0)
Note the decrease in the range by one due to the initialization row. Also note that I changed the dimensions to (1, 2) to get actual row vectors.
Much easier than appending row-wise will of course be to create the array in the wanted final shape:
my_nums = np.random.rand(100, 2)

Delete 2d subarray from 3d array in numpy

In numpy I have a 3d array and I would ike to remove some of the 2d subarrays. Think about it like this:
r = range(27)
arr = np.reshape(r, (3,3,3))
del = [[0,1,2],[0,0,2]]
flatSeam = np.ravel_multi_index(del, arr.shape)
arr = np.delete(arr, flatSeam)
So at the end I would like to have an array of the shape (3,2,3) without the elements 00, 10, 22 from the original array. My problem is that I acn not use ravel_multi_index for this, because my indices are 2d and the array shape is 3d, so the wrong indices are calculated (the code above also does not execute because the indices array and the shape have to be the same size).
Do you have any ideas how I can achieve this?
Here's an approach using advanced-indexing -
# arr: Input array, rm_idx : 2-row list/array of indices to be removed
m,n,p = arr.shape
mask = np.asarray(rm_idx[1])[:,None] != np.arange(n)
out = arr[np.arange(m)[:,None],np.where(mask)[1].reshape(m,-1)]
Alternatively, with boolean-indexing -
out = arr.reshape(-1,p)[mask.ravel()].reshape(m,-1,p)
A bit less memory-intensive approach as we try to avoid creating 2D mask -
vmask = ~np.in1d(np.arange(m*n),rm_idx[1] + n*np.arange(m))
out = arr.reshape(-1,p)[vmask].reshape(m,-1,p)

Python, from matrix to array

I have a 3d matrix grid_z0, whose dimension are (let's say) 50x25x36. Each point of this matrix represents a cell. I would like to convert this matrix into a 1D array of size 50x25x36. I would also like to create 3 array of the same size showing the coordinate of the cell center.
The array cx,cy and cz stores the coordinate of the cell center in one direction.
This example work but it rather slow, especially for large data set. Is there a way to make it faster?
data={"x":[],"y":[],"z":[],"rho":[]}
for i in arange(0,50):
for j in arange(0,25):
for k in arange(0,36):
data["x"].append(cx[i])
data["y"].append(cy[j])
data["z"].append(cz[k])
data["f"].append(grid_z0[i][j][k])
You should consider using NumPy.
>>> import numpy as np
>>> a = np.random.rand(50,25,36) # Create a fake array
>>> print a.shape
(50, 25, 36)
>>> a.shape = -1 # Flatten the array in place
>>> print a.shape
(45000,)
When flattening your array, you're doing the equivalent of :
>>> b = []
>>> for i in range(a.shape[0]):
... for j in range(a.shape[1]):
... for k in range(a.shape[2]):
... b.append(a[i,j,k])
That is, the last axis is parsed first, then the second, then the first.
Given your three 1D lists cx, cy, cz of length N, you can construct a 2D array with:
>>> centers = np.array([cx,cy,cz])
>>> print centers.shape
(3, N)
Use Numpy for matrix/array manipulation.
# convert to 1D array :
grid_1d = np.asarray(grid_z0).ravel()
For the second question, you need a 3D meshgrid. See here for an exemple :
Numpy meshgrid in 3D

Categories

Resources