Philipp
Philipp

Reputation: 662

How to generate points in a sphere and plot them with pyplot?

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: enter image description here 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

Answers (2)

Yi Bao
Yi Bao

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

caverac
caverac

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

enter image description here

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()

enter image description here

Upvotes: 1

Related Questions