Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete a set of meshgrid points inside a circle?

I am trying to create a meshgrid without some of the points that falls within the circle having specified coordinates and a radius. I am not able to subtract the grid points falling inside the circle. Here is my code

import math
import numpy 
import matplotlib.pyplot as plt


N = 50
x_start, x_end = -2.0, 2.0 
y_start, y_end = -1.0, 1.0


x = numpy.linspace(x_start, x_end, N)
y = numpy.linspace(y_start, y_end, N)

circle_x, circle_y, r= 0.0, 0.0, 0.4

#x.remove((r-circle_x)**2)   #need some help with these two lines
#y.remove((r-circle_y)**2)


X, Y = numpy.meshgrid(x, y)


size = 10
fig = plt.figure()
plt.xlabel('x', fontsize = 16)
plt.ylabel('y', fontsize = 16)
plt.scatter(X, Y)
plt.show()

meshgrid showing the mesh points## Heading

like image 302
ggulgulia Avatar asked Mar 29 '15 14:03

ggulgulia


2 Answers

If you'd like a scatter plot with just the points outside the circle, use boolean indexing to select only those points from your 2D "meshgridded" array:

import numpy as np
import matplotlib.pyplot as plt

N = 50
x_start, x_end = -2.0, 2.0
y_start, y_end = -1.0, 1.0

x = np.linspace(x_start, x_end, N)
y = np.linspace(y_start, y_end, N)

x0, y0, radius = 0.0, 0.0, 0.4

x, y = np.meshgrid(x, y)
r = np.sqrt((x - x0)**2 + (y - y0)**2)

outside = r > radius

fig, ax = plt.subplots()
ax.set(xlabel='X', ylabel='Y', aspect=1.0)

ax.scatter(x[outside], y[outside])

plt.show()

enter image description here


On the other hand, if you were using something like imshow that requires 2D input, you'd need to either mask the values inside (as @JulienSpronck mentions, though it would be better to set them to np.nan or use a masked array than to set them to 0) or set a clip path on the image.

For scatter, however, you don't need 2D input.


Boolean indexing on a nD array will return a 1d result. For example:

In [9]: x = np.arange(100).reshape(10, 10)

In [10]: x
Out[10]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
       [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])

In [11]: x[x > 75]
Out[11]: 
array([76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
       93, 94, 95, 96, 97, 98, 99])

Because scatter is only plotting points, it doesn't care how they're connected, and we can easily use the 1D result of boolean indexing.

On the other hand, if you wanted to plot an image, you'd need a 2D grid. In that case, you'd want to mask the values instead:

In [12]: np.ma.masked_where(x <= 75, x)
Out[12]: 
masked_array(data =
 [[-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- -- -- -- --]
 [-- -- -- -- -- -- 76 77 78 79]
 [80 81 82 83 84 85 86 87 88 89]
 [90 91 92 93 94 95 96 97 98 99]])

Notice how this maintains the 2D structure of the input.

On a side note, if this were a floating point array, you could just as easily set the values to np.nan instead of masking them. When plotted with imshow, the two will behave identically. I used a masked array in this case because x was an integer array and can't contain NaN's.

like image 92
Joe Kington Avatar answered Oct 13 '22 18:10

Joe Kington


One can not simply remove points from a meshgrid. Instead, you should create another array Z as

Z = numpy.where((X-circle_x)**2+(Y-circle_y)**2>r**2,1,0)

and plot it as

plt.scatter(X,Y,Z)
like image 38
plonser Avatar answered Oct 13 '22 16:10

plonser