How to draw a semicircle using matplotlib - python-3.x

I want to draw a semicircle using matplotlib.
Here I have a court
import numpy as np
import matplotlib.pyplot as plt
x_asix = np.array([0,0,100,100, 0])
y_asix = np.array([0,100,100,0, 0])
x_coordenates = np.concatenate([ x_asix])
y_coordenates = np.concatenate([y_asix])
plt.plot(x_coordenates, y_coordenates)
See image here:
I want to add one semicircle that stars at point (0,50) with radius = 10.
The result should be something like this:

Here is a function that draws semicircles, using numpy:
import matplotlib.pyplot as plt
import numpy as np
def generate_semicircle(center_x, center_y, radius, stepsize=0.1):
"""
generates coordinates for a semicircle, centered at center_x, center_y
"""
x = np.arange(center_x, center_x+radius+stepsize, stepsize)
y = np.sqrt(radius**2 - x**2)
# since each x value has two corresponding y-values, duplicate x-axis.
# [::-1] is required to have the correct order of elements for plt.plot.
x = np.concatenate([x,x[::-1]])
# concatenate y and flipped y.
y = np.concatenate([y,-y[::-1]])
return x, y + center_y
example:
x,y = generate_semicircle(0,50,10, 0.1)
plt.plot(x, y)
plt.show()

You could simply use the equation of the ellipse, to easily draw the portion of the ellipse you are interested in.
If you want to draw the part of the ellipse you have in your image, unfortunately you cannot simply write it as: y = f(x), but you can use the common trick of plotting x = f(y) instead:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1)
ax.set_aspect('equal')
x_asix = np.array([0,0,100,100, 0])
y_asix = np.array([0,100,100,0, 0])
x_coordenates = np.concatenate([ x_asix])
y_coordenates = np.concatenate([y_asix])
ax.plot(x_coordenates, y_coordenates)
# ((x - x0) / a) ** 2 + ((y - y0) / b) ** 2 == 1
a = 20
b = 15
x0 = 50
y0 = 0
x = np.linspace(-a + x0, a + x0)
y = b * np.sqrt(1 - ((x - x0) / a) ** 2) + y0
ax.plot(y, x)

Related

Slider is not updating my diagram correctly

I am trying to plot the biffurcation diagram and its equation.
My problem is that I want to put a slider for when I change the rate in the logistic map equation, but I can't seem to understand what I need to code in the update function.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
rate = np.linspace(1, 4, 1000)
N = 1000
x = np.zeros(N) + 0.5
count = np.arange(round(N*0.9), N)
y = np.zeros(N) + 0.5
#t = 1
# Biffurcation
for rs in range(len(rate)):
for n in range(N-1):
x[n+1] = rate[rs] * x[n] * (1-x[n])
u = np.unique(x[count])
r = rate[rs] * np.ones(len(u))
for i in range(N - 1):
y[i + 1] = rate[rs] * y[i] * (1 - y[i])
# plotting
plt.plot(r, u, '.', markersize=2)
plt.ylabel(ylabel='X')
plt.xlabel(xlabel='r')
plt.title('Biffurcation')
# Plotting
fig, ax = plt.subplots()
axes, = ax.plot(y, 'o-')
ax.set_ylabel(ylabel='X')
ax.set_xlabel(xlabel='Time')
ax.set_title('$x_{n+1}$ = r * $x_{n}$ * (1-$x_{n}$)')
# defining axSlider
fig.subplots_adjust(bottom=0.25)
ax_slider = fig.add_axes([0.15, 0.1, 0.65, 0.03])
slider = Slider(ax_slider, label='r', valmin=1, valmax=4, valinit=1, valstep=rate)
# updating the plot
def update(val):
current_v = slider.val
rate[rs] = current_v
axes.set_ydata(rate[rs])
fig.canvas.draw()
slider.on_changed(update)
plt.show()
I tried to update my plot for when I change the rate on my slider, but it is not working properly.
def update(val):
current_v = slider.val
rate[rs] = current_v
axes.set_ydata(rate[rs])
fig.canvas.draw()

Random function in python to generate random pair inside a circle

In python how to generate a random pair of points (x,y) that lies inside a circle of radius r.
Basically the x and y should satisfy the condition x^2 + y^2 = r^2.
To generate uniformly distributed point inside origin-centered circle of radius r, you can generate two uniform values t,u in range 0..1 and use the next formula:
import math, random
r = 4
t = random.random()
u = random.random()
x = r * math.sqrt(t) * math.cos(2 * math.pi * u)
y = r * math.sqrt(t) * math.sin(2 * math.pi * u)
print (x,y)
Using numpy to generate more than one point at a time:
import numpy as np
import matplotlib.pyplot as plt
n_samples = 1000
r = 4
# make a simple unit circle
theta = np.linspace(0, 2*np.pi, n_samples)
a, b = r * np.cos(theta), r * np.sin(theta)
t = np.random.uniform(0, 1, size=n_samples)
u = np.random.uniform(0, 1, size=n_samples)
x = r*np.sqrt(t) * np.cos(2*np.pi*u)
y = r*np.sqrt(t) * np.sin(2*np.pi*u)
# Plotting
plt.figure(figsize=(7,7))
plt.plot(a, b, linestyle='-', linewidth=2, label='Circle', color='red')
plt.scatter(x, y, marker='o', label='Samples')
plt.ylim([-r*1.5,r*1.5])
plt.xlim([-r*1.5,r*1.5])
plt.grid()
plt.legend(loc='upper right')
plt.show(block=True)
which results in:

Animating multiple Circles in each frames in Python

I am trying to create the animation in this video using Python. But I stuck on the very first step. Till now I've created a Circle and a point rotating around its circumference. My code is given below. Now I want to plot the y values corresponding to x=np.arange(0, I*np.pi, 0.01) along the x-axis (as shown in update() function in the code). For this I have to define another function to plot these x and y and pass that function inside a new animation.FuncAnimation().
Is there any way to plot everything using only the update() function?
Note I have found a code of this animation in here. But it is written in Java!
My Code
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
W = 6.5
H = 2
radius = 1
I = 2
T = 3
N = 2
plt.style.use(['ggplot', 'dark_background'])
def create_circle(x, y, r):
circle = plt.Circle((x, y), radius=r, fill=False, alpha=0.7, color='w')
return circle
def create_animation():
fig = plt.figure()
ax = plt.axes(xlim=(-2, W + 2), ylim=(-H, H))
circle = create_circle(0, 0, radius)
ax.add_patch(circle)
line1, = ax.plot(0, 1, marker='o', markersize=3, color='pink', alpha=0.7)
def update(theta):
x = radius * np.cos(theta)
y = radius * np.sin(theta)
line1.set_data([0, x], [0, y])
return line1,
anim = []
anim.append(animation.FuncAnimation(fig, update,
frames=np.arange(0, I * np.pi, 0.01),
interval=10, repeat=True))
# anim.append(animation.FuncAnimation(fig, update_line, len(x),
# fargs=[x, y, line, line1], interval=10))
plt.grid(False)
plt.gca().set_aspect('equal')
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['top'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['bottom'].set_visible(False)
plt.gca().set_xticks([])
plt.gca().set_yticks([])
plt.show()
if __name__ == '__main__':
create_animation()
Edit. I've improved the task by defining a global variable pos and changing the update() function in the following manner ...The animation now looks better but still having bugs!
Improved Portion
plot, = ax.plot([], [], color='w', alpha=0.7)
level = np.arange(0, I * np.pi, 0.01)
num = []
frames = []
for key, v in enumerate(level):
num.append(key)
frames.append(v)
def update(theta):
global pos
x = radius * np.cos(theta)
y = radius * np.sin(theta)
wave.append(y)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line1.set_data([0, x], [0, y])
pos += 1
return line1, plot,
Edit Till now I've done the following:
def update(theta):
global pos
x, y = 0, 0
for i in range(N):
prev_x = x
prev_y = y
n = 2 * i + 1
rad = radius * (4 / (n * np.pi))
x += rad * np.cos(n * theta)
y += rad * np.sin(n * theta)
wave.append(y)
circle = create_circle(prev_x, prev_y, rad)
ax.add_patch(circle)
plot.set_data(np.flip(level[:pos] + T), wave[:pos])
line2.set_data([x, T], [y, y])
line1.set_data([prev_x, x], [prev_y, y])
pos += 1
return line1, plot, line2,
Output
Please help to correct this animation. Or, is there any efficient way to do this animation?
Edit Well, now the animation is partially working. But there is a little issue: In my code (inside the definition of update()) I have to add circles centered at (prev_x, prev_y) of radius defined as rad for each frame. For this reason I try to use a for loop in the definition of update() but then all the circles remains in the figure (see the output below). But I want one circle in each frame with the centre and radius as mentioned above. Also the same problem is with the plot. I try to use ax.clear() inside the for loop but it didn't work.

Create Image using Matplotlib imshow meshgrid and custom colors

I am trying to create an image where the x axis is the width, and y axis is the height of the image. And where each point can be given a color based on a RBG mapping. From looking at imshow() from Matplotlib I guess I need to create a meshgrid on the form (NxMx3) where 3 is a tuple or something similar with the rbg colors.
But so far I have not managed to understand how to do that. Lets say I have this example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
x_min = 1
x_max = 5
y_min = 1
y_max = 5
Nx = 5 #number of steps for x axis
Ny = 5 #number of steps for y axis
x = np.linspace(x_min, x_max, Nx)
y = np.linspace(y_min, y_max, Ny)
#Can then create a meshgrid using this to get the x and y axis system
xx, yy = np.meshgrid(x, y)
#imagine I have some funcion that does someting based on the x and y values
def somefunc(x_value, y_value):
#do something and return rbg based on that
return x_value + y_value
res = somefunc(xx, yy)
cmap = LinearSegmentedColormap.from_list('mycmap', ['white', 'blue', 'black'])
plt.figure(dpi=100)
plt.imshow(res, cmap=cmap, interpolation='bilinear')
plt.show()
And this creates a plot, but what would I have to do if my goal was to give spesific rbg values based on x and y values inside somefunc and make the resulting numpy array into a N x M x 3 array
I tried to make the somefunc function return a tuple of rbg values to use (r, b g) but that does not seem to work
It will of course completely depend on what you want to do with the values you supply to the function. So let's assume you just want to put the x values as the red channel and the y values as the blue channel, this could look like
def somefunc(x_value, y_value):
return np.dstack((x_value/5., np.zeros_like(x_value), y_value/5.))
Complete example:
import numpy as np
import matplotlib.pyplot as plt
x_min = 1
x_max = 5
y_min = 1
y_max = 5
Nx = 5 #number of steps for x axis
Ny = 5 #number of steps for y axis
x = np.linspace(x_min, x_max, Nx)
y = np.linspace(y_min, y_max, Ny)
#Can then create a meshgrid using this to get the x and y axis system
xx, yy = np.meshgrid(x, y)
#imagine I have some funcion that does someting based on the x and y values
def somefunc(x_value, y_value):
return np.dstack((x_value/5., np.zeros_like(x_value), y_value/5.))
res = somefunc(xx, yy)
plt.figure(dpi=100)
plt.imshow(res)
plt.show()
If you already have a (more complicated) function that returns an RGB tuple you may loop over the grid to fill an empty array with the values of the function.
#If you already have some function that returns an RGB tuple
def somefunc(x_value, y_value):
if x_value > 2 and y_value < 3:
return np.array(((y_value+1)/4., (y_value+2)/5., 0.43))
elif x_value <=2:
return np.array((y_value/5., (x_value+3)/5., 0.0))
else:
return np.array((x_value/5., (y_value+5)/10., 0.89))
# you may loop over the grid to fill a new array with those values
res = np.zeros((xx.shape[0],xx.shape[1],3))
for i in range(xx.shape[0]):
for j in range(xx.shape[1]):
res[i,j,:] = somefunc(xx[i,j],yy[i,j])
plt.figure(dpi=100)
plt.imshow(res)

facecolor for 3d plot doesn't work

I am new to Python and trying to do a 3d plot and color it with a 4th variable. I use facecolors for this, and for one example below, it doesn't work properly. I have positive value but facecolor only displays negatives. Much appreciate if anybody looks into this.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
from scipy import ndimage
import scipy.ndimage.filters
def RP_source(theta,phi,MT):
x1 = np.sin(theta)*np.cos(phi)
x2 = np.sin(theta)*np.sin(phi)
x3 = np.cos(theta)
#
M11 = MT[0,0]
M22 = MT[1,1]
M33 = MT[2,2]
M12 = MT[0,1]
M23 = MT[1,2]
M13 = MT[0,2]
core = M11*x1*x1 + M22*x2*x2 + M33*x3*x3 + 2*M12*x1*x2 + 2*M13*x1*x3 + 2*M23*x2*x3
## S-wave
# S-wave displacement RP 3-components
us1 = (x1*M11 + x2*M12 + x3*M13) - x1*core
us2 = (x1*M12 + x2*M22 + x3*M23) - x2*core
us3 = (x1*M13 + x2*M23 + x3*M33) - x3*core
# transform S-wave displacement vector to the spherical coordinate (r,theta, phi)
USV = np.cos(theta)*np.cos(phi)*us1 + np.cos(theta)*np.sin(phi)*us2 - np.sin(theta)*us3;
return USV, us1, us2, us3
####################################################################
phi = np.linspace(0., 360., 90) # (degrees) azimuth angle with the x1-axis
theta = np.linspace(0., 180. ,45) #(degrees) angle with x3-axis (assumes positive x3 upward)
# convert to radian
theta = np.radians(theta)
phi = np.radians(phi)
theta, phi = np.meshgrid(theta, phi)
st = np.sin(theta)
ct = np.cos(theta)
sp = np.sin(phi)
cp = np.cos(phi)
# generate the propagation ray vectror
x1 = st*cp
x2 = st*sp
x3 = ct
# define moment-tensor matrix
MT = np.array([[0, 1., 0.],[1., 0., 0.],[0., 0., 0.]])
USV, us1,us2,us3 = RP_source(theta,phi,MT)
#########################
# first plot
scale = np.abs(USV)
x1_sv = scale*x1
x2_sv = scale*x2
x3_sv = scale*x3
fig =plt.figure()
ax1 = fig.gca(projection='3d')
surf1 = ax1.plot_surface(x1_sv,x2_sv,x3_sv,rstride=1, cstride=1, facecolors=cm.jet(USV), alpha=0.6)
plt.ylabel('y-axis')
plt.xlabel('x-axis')
m1 = cm.ScalarMappable(cmap=cm.jet)
m1.set_array(USV)
plt.colorbar(m1)
cm.jet wants a number in the interval [0, 1].
Replace your surf1 =... line with the following line:
surf1 = ax1.plot_surface(x1_sv,x2_sv,x3_sv,rstride=1, cstride=1, facecolors=cm.jet(USV-np.min(USV.ravel())), alpha=0.6)

Resources