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
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()
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With