Python - Break numpy array into positive and negative components - python

I have numpy arrays of shape (600,600,3), where the values are [-1.0, 1.0]. I would like to expand the array to (600,600,6), where the original values are split into the amounts above and below 0. Some examples (1,1,3) arrays, where th function foo() does the trick:
>>> a = [-0.5, 0.2, 0.9]
>>> foo(a)
[0.0, 0.5, 0.2, 0.0, 0.9, 0.0] # [positive component, negative component, ...]
>>> b = [1.0, 0.0, -0.3] # notice the behavior of 0.0
>>> foo(b)
[1.0, 0.0, 0.0, 0.0, 0.0, 0.3]

Use slicing to assign the min/max to different parts of the output array
In [33]: a = np.around(np.random.random((2,2,3))-0.5, 1)
In [34]: a
Out[34]:
array([[[-0.1, 0.3, 0.3],
[ 0.3, -0.2, -0.1]],
[[-0. , -0.2, 0.3],
[-0.1, -0. , 0.1]]])
In [35]: out = np.zeros((2,2,6))
In [36]: out[:,:,::2] = np.maximum(a, 0)
In [37]: out[:,:,1::2] = np.maximum(-a, 0)
In [38]: out
Out[38]:
array([[[ 0. , 0.1, 0.3, 0. , 0.3, 0. ],
[ 0.3, 0. , 0. , 0.2, 0. , 0.1]],
[[-0. , 0. , 0. , 0.2, 0.3, 0. ],
[ 0. , 0.1, -0. , 0. , 0.1, 0. ]]])

Related

Create a matrix using a certain vector in Python

I have this vector m = [1,0.8,0.6,0.4,0.2,0] and I have to create the following matrix in Python:
I create a matrix of zeros and a double
mm = np.zeros((6, 6))
for j in list(range(0,6,1)):
for i in list(range(0,6,1)):
ind = abs(i-j)
m[j,i] = mm[ind]
But, I got the following output:
array([[1. , 0.8, 0.6, 0.4, 0.2, 0. ],
[0.8, 1. , 0.8, 0.6, 0.4, 0.2],
[0.6, 0.8, 1. , 0.8, 0.6, 0.4],
[0.4, 0.6, 0.8, 1. , 0.8, 0.6],
[0.2, 0.4, 0.6, 0.8, 1. , 0.8],
[0. , 0.2, 0.4, 0.6, 0.8, 1. ]])
That is what I wanted! Thanks anyway.
Here is a way to implement what you want with only numpy functions, without loops (m is your numpy array):
x = np.tile(np.hstack([np.flip(m[1:]), m]), (m.size, 1))
rows, column_indices = np.ogrid[:x.shape[0], :x.shape[1]]
column_indices = column_indices - np.arange(m.size)[:, np.newaxis]
result = x[rows, column_indices][:, -m.size:]
Example:
>>> result
array([[1. , 0.8, 0.6, 0.4, 0.2, 0. ],
[0.8, 1. , 0.8, 0.6, 0.4, 0.2],
[0.6, 0.8, 1. , 0.8, 0.6, 0.4],
[0.4, 0.6, 0.8, 1. , 0.8, 0.6],
[0.2, 0.4, 0.6, 0.8, 1. , 0.8],
[0. , 0.2, 0.4, 0.6, 0.8, 1. ]])
This approach is much faster than using a list comprehension when m is large.
This could be written by comprehension if you do not want to use numpy,
[m[i::-1] + m[1:len(m)-i] for i in range(len(m))]

Index array with the result of .nonzero()

I am having difficulties selecting rows using two condition in Numpy. The following code does not return the intended output
tot_length=0.3
steps=0.1
start_val=0.0
list_no =np.arange(start_val, tot_length, steps)
x, y, z = np.meshgrid(*[list_no for _ in range(3)], sparse=True)
a = ((x>=y) & (y>=z)).nonzero() # this maybe the problem
output
(array([0, 0, 0, 1, 1, 1, 1, 2, 2, 2]), array([0, 1, 2, 1, 1, 2, 2, 2, 2, 2]), array([0, 0, 0, 0, 1, 0, 1, 0, 1, 2]))
whereas, the intended output
[[0. 0. 0. ]
[0.1 0. 0. ]
[0.1 0.1 0. ]
[0.1 0.1 0.1]
[0.2 0. 0. ]
[0.2 0.1 0. ]
[0.2 0.1 0.1]
[0.2 0.2 0. ]
[0.2 0.2 0.1]
[0.2 0.2 0.2]]
ndarray.nonzero as well as np.where return tuples of arrays of indices. This makes unpacking those indices into separate arrays, which can then be used to index along a given axis. Stacking them up into a 2D array is trivial though, simply build a new array and transpose as:
ix = np.array(((x>=y) & (y>=z)).nonzero()).T
Then you can easily use the array of indices to index list_no as:
list_no[ix]
array([[0. , 0. , 0. ],
[0. , 0.1, 0. ],
[0. , 0.2, 0. ],
[0.1, 0.1, 0. ],
[0.1, 0.1, 0.1],
[0.1, 0.2, 0. ],
[0.1, 0.2, 0.1],
[0.2, 0.2, 0. ],
[0.2, 0.2, 0.1],
[0.2, 0.2, 0.2]])

I have 8 vertices of a box on a 3D terrain, and i need to seperate the box to a few smaller ones

For this problem, I got the 8 vertices of a box that i need to shrink, with a given size that is an integer which I need to shrink every side with. For example, if the size of the box I need to shrink is 8*8*8 and the shrinking size is 2, I need to return a list of all the vertices of the 4*4*4 boxes that fill the big box in a 3D coordinate system.
I thought about having a for loop that runs in range of the size of the box, but than I thought if I want to eventually seperate the box into a lot more boxes that are smaller and I want to fill the big box i would have to write an amount of code that I wouldn't be able to write. How to get this list of vertices without writing this much code?
I'm not sure if this is what you want, but here is a simple way to compute vertices in a grid with NumPy:
import numpy as np
def make_grid(x_size, y_size, z_size, shrink_factor):
n = (shrink_factor + 1) * 1j
xx, yy, zz = np.mgrid[:x_size:n, :y_size:n, :z_size:n]
return np.stack([xx.ravel(), yy.ravel(), zz.ravel()], axis=1)
print(make_grid(8, 8, 8, 2))
Output:
[[0. 0. 0.]
[0. 0. 4.]
[0. 0. 8.]
[0. 4. 0.]
[0. 4. 4.]
[0. 4. 8.]
[0. 8. 0.]
[0. 8. 4.]
[0. 8. 8.]
[4. 0. 0.]
[4. 0. 4.]
[4. 0. 8.]
[4. 4. 0.]
[4. 4. 4.]
[4. 4. 8.]
[4. 8. 0.]
[4. 8. 4.]
[4. 8. 8.]
[8. 0. 0.]
[8. 0. 4.]
[8. 0. 8.]
[8. 4. 0.]
[8. 4. 4.]
[8. 4. 8.]
[8. 8. 0.]
[8. 8. 4.]
[8. 8. 8.]]
Otherwise with itertools:
from itertools import product
def make_grid(x_size, y_size, z_size, shrink_factor):
return [(x * x_size, y * y_size, z * z_size)
for x, y, z in product((i / shrink_factor
for i in range(shrink_factor + 1)), repeat=3)]
print(*make_grid(8, 8, 8, 2), sep='\n')
Output:
(0.0, 0.0, 0.0)
(0.0, 0.0, 4.0)
(0.0, 0.0, 8.0)
(0.0, 4.0, 0.0)
(0.0, 4.0, 4.0)
(0.0, 4.0, 8.0)
(0.0, 8.0, 0.0)
(0.0, 8.0, 4.0)
(0.0, 8.0, 8.0)
(4.0, 0.0, 0.0)
(4.0, 0.0, 4.0)
(4.0, 0.0, 8.0)
(4.0, 4.0, 0.0)
(4.0, 4.0, 4.0)
(4.0, 4.0, 8.0)
(4.0, 8.0, 0.0)
(4.0, 8.0, 4.0)
(4.0, 8.0, 8.0)
(8.0, 0.0, 0.0)
(8.0, 0.0, 4.0)
(8.0, 0.0, 8.0)
(8.0, 4.0, 0.0)
(8.0, 4.0, 4.0)
(8.0, 4.0, 8.0)
(8.0, 8.0, 0.0)
(8.0, 8.0, 4.0)
(8.0, 8.0, 8.0)
A solution using numpy, which allows easy bloc manipulation.
First I choose to represent a cube with an origin and three vectors : the unit cube is represented with orig=np.array([0,0,0]) and vects=np.array([[1,0,0],[0,1,0],[0,0,1]]).
Now a numpy function to generate the eight vertices:
import numpy as np
def cube(origin,edges):
for e in edges:
origin = np.vstack((origin,origin+e))
return origin
cube(orig,vects)
array([[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 1],
[1, 1, 1]])
Then an other to span minicubes in 3D :
def split(origin,edges,k):
minicube=cube(origin,edges/k)
for e in edges/k:
minicube =np.vstack([minicube + i*e for i in range(k) ])
return minicube.reshape(k**3,8,3)
split (orig,vects,2)
array([[[ 0. , 0. , 0. ],
[ 0.5, 0. , 0. ],
[ 0. , 0.5, 0. ],
[ 0.5, 0.5, 0. ],
[ 0. , 0. , 0.5],
[ 0.5, 0. , 0.5],
[ 0. , 0.5, 0.5],
[ 0.5, 0.5, 0.5]],
...
[[ 0.5, 0.5, 0.5],
[ 1. , 0.5, 0.5],
[ 0.5, 1. , 0.5],
[ 1. , 1. , 0.5],
[ 0.5, 0.5, 1. ],
[ 1. , 0.5, 1. ],
[ 0.5, 1. , 1. ],
[ 1. , 1. , 1. ]]])
My example below will work on a generic box and assumes integer coordinates.
import numpy as np
def create_cube(start_x, start_y, start_z, size):
return np.array([
[x,y,z]
for z in [start_z, start_z+size]
for y in [start_y, start_y+size]
for x in [start_x, start_x+size]
])
def subdivide(box, scale):
start = np.min(box, axis=0)
end = np.max(box, axis=0) - scale
return np.array([
create_cube(x, y, z, scale)
for z in range(start[2], end[2]+1)
for y in range(start[1], end[1]+1)
for x in range(start[0], end[0]+1)
])
cube = create_cube(1, 3, 2, 8)
Cube will look like:
array([[ 1, 3, 2],
[ 9, 3, 2],
[ 1, 11, 2],
[ 9, 11, 2],
[ 1, 3, 10],
[ 9, 3, 10],
[ 1, 11, 10],
[ 9, 11, 10]])
Running the following subdivide:
subcubes = subdivide(cube, 2)
The subdivide function creates an nparray with a shape: (343, 8, 3). You would expect to have 343 subcubes moving the 2x2 cube evenly over an 8x8 cube.

How to flatten a 3d array of sliding window into 2d array?

I'm using an Autoencoder LSTM in python(Keras). I have a multivariate input and I use a sliding window approach to convert it to the proper format of LSTM input. In the end, I get the output with the same shape as the window.
Then I want to convert this array to the original input shape. Can anyone help me how should I do this?
This is my code to put a sliding window on a multivariate signal:
def window(samples, windows_size, step):
m, n = samples.shape
print("\nold shape: ", m, "*", n)
num_signals = n
num_samples = (samples.shape[0] - windows_size) // step + 1
aa = np.empty([num_samples, windows_size, num_signals])
for j in range(num_samples):
for i in range(num_signals):
aa[j, :, i] = samples[(j * step):(j * step + windows_size), i]
samples = aa
m ,n, k = samples.shape
print("new shape: ", m, "*", n, "*", k)
return samples
x = np.asarray([[1,0.1,0.1],[2,0.2,0.2],[3,0.3,0.3],[4,0.4,0.4],
[5,0.5,0.5],[6,0.6,0.6],[7,0.7,0.7],[8,0.8,0.8]])
window(x, 3, 2)
old shape: 8 * 3
new shape: 3 * 3 * 3
Out[65]:
array([[[1. , 0.1, 0.1],
[2. , 0.2, 0.2],
[3. , 0.3, 0.3]],
[[3. , 0.3, 0.3],
[4. , 0.4, 0.4],
[5. , 0.5, 0.5]],
[[5. , 0.5, 0.5],
[6. , 0.6, 0.6],
[7. , 0.7, 0.7]]])
You can use this:
Note: stride is the same concept as in CNNs, number of elements you skip to get the next window.
inp = np.array([[[1. , 0.1, 0.1],
[2. , 0.2, 0.2],
[3. , 0.3, 0.3]],
[[3. , 0.3, 0.3],
[4. , 0.4, 0.4],
[5. , 0.5, 0.5]],
[[5. , 0.5, 0.5],
[6. , 0.6, 0.6],
[7. , 0.7, 0.7]]])
def restitch(array, stride):
flat = array.flatten().reshape(-1,array.shape[2])
keep = [i for i in range(len(flat)) if not(i%(stride+1)==0 and i>0)]
return flat[keep]
restitch(inp, 2)
array([[1. , 0.1, 0.1],
[2. , 0.2, 0.2],
[3. , 0.3, 0.3],
[4. , 0.4, 0.4],
[5. , 0.5, 0.5],
[6. , 0.6, 0.6],
[7. , 0.7, 0.7]])

4 x 4 Floats to numpy Matrix

Following numpy command:
c = np.matrix('1,0,0,0;0,1,0,0;0,0,1,0;-6.6,1.0,-2.8, 1.0')
creates a matrix Outupt:
[[ 1. 0. 0. 0. ]
[ 0. 1. 0. 0. ]
[ 0. 0. 1. 0. ]
[-6.6 1. -2.8 1. ]]
However my Input is a comma-separated array of floats :
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -6.604560409595856, 1.0, -2.81542864114781, 1.0]
Is there a simple way of getting those floats, easily into a numpy matrix by defining the shape in before as a 4 x 4 matrix?
np.array([1.0, 0.0,..., -2.81542864114781, 1.0]).reshape((4, 4))

Categories