I am trying to generate random points on the surface of the sphere using numpy. I have reviewed the post that explains uniform distribution here. However, need ideas on how to generate the points only on the surface of the sphere. I have coordinates (x, y, z) and the radius of each of these spheres.
I am not very well-versed with Mathematics at this level and trying to make sense of the Monte Carlo simulation.
Any help will be much appreciated.
Thanks, Parin
random points can be picked on a unit sphere in the Wolfram Language using the function RandomPoint[Sphere[], n]. have a uniform distribution on the surface of a unit sphere. This method can also be extended to hypersphere point picking.
An alternative method to generate uniformly disributed points on a unit sphere is to generate three standard normally distributed numbers X, Y, and Z to form a vector V=[X,Y,Z]. Intuitively, this vector will have a uniformly random orientation in space, but will not lie on the sphere.
Mapping the Fibonacci lattice (aka Golden Spiral, aka Fibonacci Sphere) onto the surface of a sphere is an extremely fast and effective approximate method to evenly distribute points on a sphere.
Based on the last approach on this page, you can simply generate a vector consisting of independent samples from three standard normal distributions, then normalize the vector such that its magnitude is 1:
import numpy as np
def sample_spherical(npoints, ndim=3):
vec = np.random.randn(ndim, npoints)
vec /= np.linalg.norm(vec, axis=0)
return vec
For example:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d
phi = np.linspace(0, np.pi, 20)
theta = np.linspace(0, 2 * np.pi, 40)
x = np.outer(np.sin(theta), np.cos(phi))
y = np.outer(np.sin(theta), np.sin(phi))
z = np.outer(np.cos(theta), np.ones_like(phi))
xi, yi, zi = sample_spherical(100)
fig, ax = plt.subplots(1, 1, subplot_kw={'projection':'3d', 'aspect':'equal'})
ax.plot_wireframe(x, y, z, color='k', rstride=1, cstride=1)
ax.scatter(xi, yi, zi, s=100, c='r', zorder=10)
The same method also generalizes to picking uniformly distributed points on the unit circle (ndim=2
) or on the surfaces of higher-dimensional unit hyperspheres.
Points on the surface of a sphere can be expressed using two spherical coordinates, theta
and phi
, with 0 < theta < 2pi
and 0 < phi < pi
.
Conversion formula into cartesian x, y, z
coordinates:
x = r * cos(theta) * sin(phi)
y = r * sin(theta) * sin(phi)
z = r * cos(phi)
where r
is the radius of the sphere.
So the program could randomly sample theta
and phi
in their ranges, at uniform distribution, and generate the cartesian coordinates from it.
But then the points get distributed more densley on the poles of the sphere. In order for points to get uniformly distributed on the sphere surface, phi
needs to be chosen as phi = acos(a)
where -1 < a < 1
is chosen on an uniform distribution.
For the Numpy code it would be the same as in Sampling uniformly distributed random points inside a spherical volume , except that the variable radius
has a fixed value.
Another way that depending on the hardware could be much faster.
Choose a, b, c
to be three random numbers each between -1 and 1
Calculate r2 = a^2 + b^2 + c^2
If r2 > 1.0 (=the point isn't in the sphere) or r2 < 0.00001 (=the point is too close to the center, we'll have division by zero while projecting to the surface of the sphere) you discard the values, and pick another set of random a, b, c
Otherwise, you’ve got your random point (relative to center of the sphere):
ir = R / sqrt(r2)
x = a * ir
y = b * ir
z = c * ir
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