Reputation: 662
I am using this method to give me a list of points inside a sphere. However when I plot the result it does not look spherical at all. There must be something wrong with the logic here. What could it be?
def give_sphere(x, y, z, r, num):
"""The distribution of dots in the sphere increases towards the center.
Return: A List of Points (x,y,z) which are all inside the sphere."""
points = []
for i in range(0, num):
factor = normedgauss() # A value between 0 and 1 following a gaussian
ir = r * factor
ix = x + ir * np.cos(npi())
iy = y + ir * np.sin(npi())
iz = z + ir * np.cos(npi())
points.append((ix, iy, iz))
return points
This is the 3D plot: Also I want to plot this list of points using pyplot in 3D. I can achieve that with the following code, but then I cannot add another point cloud for display in the same diagram. How will I do that?
def plot_sphere(points):
x_list = [x for [x, y, z] in points]
y_list = [y for [x, y, z] in points]
z_list = [z for [x, y, z] in points]
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(x_list, y_list, z_list)
plt.show()
Upvotes: 1
Views: 1705
Reputation: 164
Your first question is about Monte Carlo simulation based on a distribution function. Generally, one needs to derive a specific sampling scheme using the probability density function.
I assume you would like to have uniformly distributed points within a sphere. I would recommend one the best links which clearly demonstrates the whole process for your case and encourage you to explore the pros and cons:
Generating uniformly distributed numbers on a sphere.
Upvotes: 1
Reputation: 1637
Probably you are generating the angle using uniformly distributed random numbers, and that's is not the case. The volume differential in 3D is something like (dr^3)(d cos theta) (d phi)
, that means that the variable that is uniformly distributed is cos theta
, not theta
(same goes for the radial component, but I'm not sure what you are trying to to, so I left it untouched)
def give_sphere(x, y, z, r, num):
points = []
for i in range(0, num):
factor = normedgauss() # A value between 0 and 1 following a gaussian
ir = r * factor
itheta = np.arccos(np.random.uniform(-1, 1))
iphi = np.random.uniform(0, 2 * np.pi)
ix = x + ir * np.sin(itheta) * np.cos(iphi)
iy = y + ir * np.sin(itheta) * np.sin(iphi)
iz = z + ir * np.cos(itheta)
points.append((ix, iy, iz))
return points
With this in mind, this is what you should get
As for the second problem
def plot_sphere(points, ax):
x_list = [x for [x, y, z] in points]
y_list = [y for [x, y, z] in points]
z_list = [z for [x, y, z] in points]
ax.scatter(x_list, y_list, z_list)
fig = plt.figure()
ax = Axes3D(fig)
points1 = give_sphere(0, 0, -2, 1, 1000)
points2 = give_sphere(0, 0, 2, 1, 1000)
plot_sphere(points1, ax)
plot_sphere(points2, ax)
plt.show()
Upvotes: 1