Search code examples
pythonnumpymatplotlibrandomcoordinates

Random Uniform 3D Distribution of Points Inside a Spherical Shell of Inner and Outer Radius


I'm trying to generate (as efficiently as possible), a random uniform, 3D distribution of points inside of a sphere of an inner radius r_min and outer radius r_max,i.e. a shell. I found a similar solution here: Sampling uniformly distributed random points inside a spherical volume, however this is only true for a whole sphere of r_min=0 and r_max=1. This is done using the following code:

r     = r_max*np.cbrt(np.random.uniform(low=r_min,high=r_max,size=nsamp))
phi   = np.random.uniform(0,2*np.pi,nsamp)
theta = np.arccos( np.random.uniform(-1,1,nsamp)

When r_min=0 and r_max=1.0, it produces the expected result (2D projection along x-y):

enter image description here

However, when I change either r_max or r_min to anything other than 0 and 1, I do not get the expected results, and this is likely due to the usage of np.cbrt(). How can I properly generate uniform random points on this spherical shell while specifying inner and outer radii?


Solution

  • From https://math.stackexchange.com/questions/1885630/random-multivariate-in-hyperannulus, one can randomly sample radii from a uniform distribution in the geometry of an n-dimensionsal hyperannulus, which in n=3 dimensions, is a spherical shell of inner radius r_min and outer r_out. The code to do this is

    u     = np.random.uniform(0,1,size=nsamp) # uniform random vector of size nsamp
    r     = np.cbrt((u*r_max**3)+((1-u)*r_min**3))
    phi   = np.random.uniform(0,2*np.pi,nsamp)
    theta = np.arccos( np.random.uniform(-1,1,nsamp) )
    

    which produces the expected distribution when specifying r_min and r_out.