How to append all subdivided polygon coordinates? - python

let A be set of coordinate (e.g. array([[ 10., 110.],[200., 90.],[210., 0.], [-10., 10.],[ 10., 110.]]).
If subdivision(coordinate) is a division code, giving two outcomes - subdivisionR, subdivisionL, then subdivision(A) gives array([[ 10., 110.],[110.0, 99.47],[110.0, 4.54],[-10., 10.],[ 10., 110.]]), array([[110.0, 99.47],[200.,90.],[210., 0.],[110.0, 4.54],[110.0, 99.47]]).
Since I wanted to divide the polygon until all subdivided polygons reach the area closest to 200 and get all subdivided coordinates, I used following code;
n=1
t=0
r=0
k=A
while area(subdivision(k)[n-1])>200:
for i in range(t,n):
k.append(subdivision(k[i])[0])
k.append(subdivision(k[i])[1])
t=2**r
r=r+1
n=2**r
However, I get warning - 'numpy.ndarray' object has no attribute 'append'.
How can I fix this?

The syntax for appending to a numpy array is different to say that of a python list. You want to use:
numpy.append(array, value, axis)
So something like:
numpy.append(k, subdivision(k[i]), axis = 0)
Note axis is optional and would default to 1. 'value' is a numpy array, not a discrete value.

Related

How to extrapolate points of a regular grid in python

I have a numpy array of points and want to extend my point (x, y and z) in a defined direction. This is my array:
coordinates=np.array([[1., 19., 4.], [2., 19., 4.5], [1., 20., 4.],[2., 20., 4.5], [3., 20., 4.]])
These points are on two y grids: 19 and 20. I want to extend my points in these grid lines. First grid has two point. x and y coordinates of extrapolated points are fixed. y equals the grid value (19 or 20) and x equals one unit more that the last point of the grid. For first grid the new x and y of two points are (3.,19.) and (4.,19.) and z should be calculated as:
z of last point + (z of last point - z of one point before the last)/2
In case of having just one point in the grid, I copy the value of that point. In the first grid, z value of first extrapolated point is :
4.5 + (4.5-4)/2 = 4.75
and for the second point is
4.75 + (4.75-4.5)/2 = 4.875
I want to do the same for the next grid (y=20) to finally add all four point to the existing array:
all_points=np.array([[1.,19.,4.], [1.,20.,4.], [2.,19.,4.5], [2.,20.,4.5], [3.,20.,4.],\
[3.,19.,4.75], [4.,19.,4.875], [4.,20,3.75], [5.,20, 3.625]])
I tried the following but firstly I have no idea how to generate z value dynamically. At the moment it is calculating the same z values for the new two generated points of each grid. Another issue is that my code is not effiecient and I believe there are much faster ways to do it:
nums, counts=np.unique(coordinates[:,1],return_counts=True) # gives the y grids
new_y=nums
cum=np.cumsum(counts)-1
new_x=[]
for i in cum:
new_x.append (coordinates[i,0])
new_x=np.array(new_x)
new_x_y=[]
for m, n in zip (new_x, new_y):
new_x_y.append([m,n])
new_x_y.append([m+1,n])
new_x_y=np.array(new_x_y)
z_difference=[]
for i in cum:
z_difference.append((coordinates[i,-1]-coordinates[i-1,-1])/2)# to find the difference of last two points of each grid
new_z=[]
for i in range (len(cum)-1):
new_z.append (coordinates[cum[i],-1]+z_difference)#to find the new z of each extrapolated point
new_z=np.array(new_z)
all_z=np.repeat (new_z, repeats=new_z.shape[1], axis=1)
final_arr=np.hstack ([new_x_y, all_z.T])
In advance, I do appreciate any help to solve my problem in python.

Is there a quick way to ignore certain values of an array when performing numpy operations?

Sorry if the title is confusing, but it is very hard to put what I would like to do in a single sentence. Image you have an image stack stack in the form of N m x n matrices as a numpy array in the shape of (m, n, N). Now, if I want to perform the numpy.median for example along the stack axis N it is very easy: numpy.median(stack, 0). The problem is that for each image of the stack, I also have a mask of pixels that I would not like to include in the operation, in this case numpy.median. Is there any efficient way to do that?
So far, all I could think of is this, but it is increadibly slow and absolutely not feasible:
median = [[]]*images[0].flatten().shape
for i in range(len(images)):
image = images[i].flatten()
mask = mask[i].flatten()
for j in range(len(median)):
if mask[j] == 0:
median[j].append(image[j])
for i in range(len(median)):
median[j] = np.median(median[j]) if median[j] else 0
median = np.array(median).reshape(images[0].shape)
There has to be a better way.
What you can do is build a an array with NaNs in the non-masked values and compute np.nanmedian (which ignores NaNs). You can build such an array "on the fly" using np.where:
x = np.arange(4*3*4).reshape((4,3,4))
m = x%2 == 0
np.nanmedian(np.where(m, x, np.NaN), axis=2)
>>array([[ 1., 5., 9.],
[13., 17., 21.],
[25., 29., 33.],
[37., 41., 45.]])
I have a hard time understanding what you are trying to say, but hopefully this will help:
You can use np.whereto find and replace - or ignore/remove - values that you want to exclude.
Or you can use bin_mask = stack != value_you_want_to_ignore to get a boolean array that you can use to ignore your critical values.

how to incorporate two types in one loop in python

If subdivision(coordinate) is a division code using bounding box theory, giving two outcomes - subdivisionR, subdivisionL;
A = array([[ 10., 110.],[200., 90.],[210., 0.], [-10., 10.],[ 10., 110.]])
subdivision(A) = array([[ 10., 110.],[110.0, 99.47],[110.0, 4.54],[-10., 10.],[ 10., 110.]]),
array([[110.0, 99.47],[200.,90.],[210., 0.],[110.0, 4.54],[110.0, 99.47]])
area(A) = 19550.0
subdivision(A)
Since I want to repeat subdivision() for all subdivided polygons until each area reaches near 200, I made below code. However, tuple index for area() is a single integer and tuple index for subdivision() is array of coordinates. If I want to append all subdivided polygons until each area reaches 200 in a list of coordinates, how can I fix the code below?
n=1
t=0
r=0
k=A
while area(subdivision(k)[n-1])>200:
for i in range(t,n):
np.append(k[0],subdivision(k)[0])[i]
np.append(k[1],subdivision(k)[1])[i]
t=2**r
r=r+1
n=2**r

Python move point by matrix and then draw orbit

I know how to draw points moved by matrix, like this below
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
x=np.random.randn(2) #2*1 matrix
A=np.random.randn(2,2) #2*2 matrix
print ('the content of x:\n{}\n the content of A:\n{}'.format(x,A))
def action(pt,n):
record=[pt]
for i in range(n):
pt= A#pt
record=np.vstack([record,pt])
plt.scatter(record[:,1],record[:,1])
action(x,100)
the function "action" will draw something like a line, but I want to move points by matrix and then draw it like an orbit
SHORT ANSWER:
plt.scatter(record[:,1],record[:,1]) will feed same values in both x & y dimensions & hence will always return a line. Replace it by:
X,Y = np.hsplit(record,2)
plt.scatter(X,Y)
LONG ANSWER:
The main cause behind plot coming out as a line is that you are generating the plot using 2 constants (although randomly generated). I will illustrate using below example:
>>> c
array([[ 1., 2.],
[ 2., 4.]])
>>> d
array([ 3., 4.])
>>> d#c
array([ 11., 22.])
>>> d#c#c
array([ 55., 110.])
>>> d#c#c#c
array([ 275., 550.])
Notice how all the recursive operation is only multiplying the initial co-ordinate by 5 at each stage.
How to get a non-linear plot??
Utilize the variable 'i' which we are calling for loop operation by giving it a power of 2(parabola) or more.
Use random numbers populated in the 2 matrices greater than 1. Otherwise all the operations either increase the magnitude in -ve or if b/w (-1,1) the magnitude decreases.
Use mathematical functions to introduce non-linearity. Eg:
pt = pt + np.sin(pt)
Reflect if using 2 random matrices & looping over them is the only way to achieve the curve. If this activity is independent from your bigger programme etc, then probably try different approach by using mathematical functions which generate the curve you like.

Normalise 2D Numpy Array: Zero Mean Unit Variance

I have a 2D Numpy array, in which I want to normalise each column to zero mean and unit variance. Since I'm primarily used to C++, the method in which I'm doing is to use loops to iterate over elements in a column and do the necessary operations, followed by repeating this for all columns. I wanted to know about a pythonic way to do so.
Let class_input_data be my 2D array. I can get the column mean as:
column_mean = numpy.sum(class_input_data, axis = 0)/class_input_data.shape[0]
I then subtract the mean from all columns by:
class_input_data = class_input_data - column_mean
By now, the data should be zero mean. However, the value of:
numpy.sum(class_input_data, axis = 0)
isn't equal to 0, implying that I have done something wrong in my normalisation. By isn't equal to 0, I don't mean very small numbers which can be attributed to floating point inaccuracies.
Something like:
import numpy as np
eg_array = 5 + (np.random.randn(10, 10) * 2)
normed = (eg_array - eg_array.mean(axis=0)) / eg_array.std(axis=0)
normed.mean(axis=0)
Out[14]:
array([ 1.16573418e-16, -7.77156117e-17, -1.77635684e-16,
9.43689571e-17, -2.22044605e-17, -6.09234885e-16,
-2.22044605e-16, -4.44089210e-17, -7.10542736e-16,
4.21884749e-16])
normed.std(axis=0)
Out[15]: array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

Categories