Rahat Zaman
Rahat Zaman

Reputation: 1382

How to create a circle with uniformly distributed dots in the perimeter of it with scatterplot in python

Suppose I have a circle x**2 + y**2 = 20. Now I want to plot the circle with n_dots number of dots in the circles perimeter in a scatter plot. So I created the code like below:

n_dots = 200
x1 = np.random.uniform(-20, 20, n_dots//2)
y1_1 = (400 - x1**2)**.5
y1_2 = -(400 - x1**2)**.5
plt.figure(figsize=(8, 8))
plt.scatter(x1, y1_1, c = 'blue')
plt.scatter(x1, y1_2, c = 'blue')
plt.show()

But this shows the dots not uniformly distributed all the places in the circle. The output is :

output scatter plot

So how to create a circle with dots in scatter plot where all the dots are uniformly distributed in the perimeter of the circle?

Upvotes: 2

Views: 2664

Answers (2)

f5r5e5d
f5r5e5d

Reputation: 3706

for a very generalized answer that also works in 2D:

import numpy as np
import matplotlib.pyplot as plt


def u_sphere_pts(dim, N):
    """
    uniform  distribution points on hypersphere
    from uniform distribution in n-D (<-1, +1>) hypercube,
    clipped by unit 2 norm to get the points inside the insphere,
    normalize selected points to lie on surface of unit radius hypersphere
    """
    # uniform points in hypercube
    u_pts = np.random.uniform(low=-1.0, high=1.0, size=(dim, N))

    # n dimensional 2 norm squared
    norm2sq = (u_pts**2).sum(axis=0)

    # mask of points where 2 norm squared  < 1.0
    in_mask = np.less(norm2sq, np.ones(N))

    # use mask to select points, norms inside unit hypersphere
    in_pts = np.compress(in_mask, u_pts, axis=1)
    in_norm2 = np.sqrt(np.compress(in_mask, norm2sq))  # only sqrt selected

    # return normalized points, equivalently, projected to hypersphere surface
    return in_pts/in_norm2


# show some 2D "sphere" points
N = 1000
dim = 2
fig2, ax2 = plt.subplots()
ax2.scatter(*u_sphere_pts(dim, N))
ax2.set_aspect('equal')
plt.show()

enter image description here

# plot histogram of angles

pts = u_sphere_pts(dim, 1000000)
theta = np.arctan2(pts[0,:], pts[1,:])
num_bins = 360
fig1, ax1 = plt.subplots()
n, bins, patches = plt.hist(theta, num_bins, facecolor='blue', alpha=0.5)
plt.show()

enter image description here

similar/related: https://stackoverflow.com/questions/45580865/python-generate-an-n-dimensional-hypercube-using-rejection-sampling#comment78122144_45580865

Python Uniform distribution of points on 4 dimensional sphere

http://mathworld.wolfram.com/HyperspherePointPicking.html

Sampling uniformly distributed random points inside a spherical volume

Upvotes: 1

swatchai
swatchai

Reputation: 18782

A simple way to plot evenly-spaced points along the perimeter of a circle begins with dividing the whole circle into equally small angles where the angles from circle's center to all points are obtained. Then, the coordinates (x,y) of each point can be computed. Here is the code that does the task:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(8, 8))

n_dots = 120   # set number of dots
angs = np.linspace(0, 2*np.pi, n_dots)  # angles to the dots
cx, cy = (50, 20)  # center of circle
xs, ys = [], []    # for coordinates of points to plot
ra = 20.0          # radius of circle

for ang in angs:
    # compute (x,y) for each point
    x = cx + ra*np.cos(ang)
    y = cy + ra*np.sin(ang)
    xs.append(x)   # collect x
    ys.append(y)   # collect y

plt.scatter(xs, ys, c = 'red', s=5)  # plot points 
plt.show()

The resulting plot: enter image description here

Alternately, numpy's broadcasting nature can be used and shortened the code:

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure(figsize=(8, 8))

n_dots = 120   # set number of dots
angs = np.linspace(0, 2*np.pi, n_dots)  # angles to the dots
cx, cy = (50, 20)  # center of circle
ra = 20.0          # radius of circle

# with numpy's broadcasting feature...
# no need to do loop computation as in above version
xs = cx + ra*np.cos(angs)
ys = cy + ra*np.sin(angs)

plt.scatter(xs, ys, c = 'red', s=5)  # plot points 
plt.show()

Upvotes: 4

Related Questions