How to plot equation - python-3.x

How to plot these equations please? The output is empty - there are only axes but no line
import numpy as np
import matplotlib.pyplot as plt
r = 50
a = 5
n = 20
t = 5
x = (r + a * np.sin(n * t * 360 )) * np.cos (t * 360 )
y = (r + a * np.sin(n * t * 360 )) * np.sin (t * 360 )
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()

You are currently just calculating single values for x and y:
>>> import numpy as np
>>> r, a, n, t = 50, 5, 20, 5
>>> x = (r + a * np.sin(n * t * 360 )) * np.cos (t * 360 )
>>> y = (r + a * np.sin(n * t * 360 )) * np.sin (t * 360 )
>>> print(x, y)
-47.22961311822641 6.299155241288046
This means there is no line for matplotlib to plot.
To plot a line, you have to pass two or more points for matplotlib to draw lines between.
import matplotlib.pyplot as plt
import numpy as np
t = np.linspace(0, 2*np.pi, 100) # create an array of 100 points between 0 and 2*pi
x = np.sin(2*t)
y = np.cos(t)
plt.plot(x, y)
plt.show()
Or in your case:
t = np.linspace(0, 2*np.pi, 1000)
# removed the factor *360 as numpy's sin/cos works with radians by default
x = (r + a * np.sin(n * t)) * np.cos(t)
y = (r + a * np.sin(n * t)) * np.sin(t)
plt.plot(x, y)
plt.show()

You are evaluating the function just at t=5. You should give a range of values to evaluate. If you change t variable to, for example
t= np.array([0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1])
you will see a graph. But it is up to you to define the range and the step for your needs

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

How to fill between two lines with different x and y?

How to fill between two lines with different x and y? Now, the filling is for two y functions with the common x-axis, which is not true. When I tried x1, x2, y1, y2 I have got a worse result than displayed below.
import matplotlib.pyplot as plt
import numpy as np
from numpy import exp, sin
def g(y):
amp = 0.6
return amp*exp(-2.5*y)*sin(9.8*y)
def g_e(y):
amp = 0.66
return amp*exp(-2.5*y_e)*sin(8.1*y_e)
y = np.linspace(0, 0.83, 501)
y_e = np.linspace(0, 1.08, 501)
values = g(y)
values_e = g_e(y)
theta = np.radians(-65.9)
c, s = np.cos(theta), np.sin(theta)
rot_matrix = np.array(((c, s), (-s, c)))
xy = np.array([y, values]).T # rot_matrix
theta_e = np.radians(-60)
c_e, s_e = np.cos(theta_e), np.sin(theta_e)
rot_matrix_e = np.array(((c_e, s_e), (-s_e, c_e)))
xy_e = np.array([y, values_e]).T # rot_matrix_e
fig, ax = plt.subplots(figsize=(5,5))
ax.axis('equal')
x_shift = 0.59
y_shift = 0.813
x_shift_e = 0.54
y_shift_e = 0.83
ax.plot(xy[:, 0]+x_shift, xy[:, 1]+y_shift, c='red')
ax.plot(xy_e[:, 0]+x_shift_e, xy_e[:, 1]+y_shift_e, c='black')
ax.fill_between(xy[:, 0]+x_shift, xy[:, 1]+y_shift, xy_e[:, 1]+y_shift_e)
plt.show()
Script for additional question:
for i in range(len(x)-1):
for j in range(i-1):
xs_ys = intersection(x[i],x[i+1],x[j],x[j+1],y[i],y[i+1],y[j],y[j+1])
if xs_ys in not None:
xs.append(xs_ys[0])
ys.append(xs_ys[1])
I got an error:
if xs_ys in not None:
^
SyntaxError: invalid syntax
Here is an approach creating a "polygon" by concatenating the reverse of one curve to the other curve. ax.fill() can be used to fill the polygon. Note that fill_between() can look strange when the x-values aren't nicely ordered (as is the case here after the rotation). Also, the mirror function fill_betweenx() wouldn't be adequate in this case.
import matplotlib.pyplot as plt
import numpy as np
def g(y):
amp = 0.6
return amp * np.exp(-2.5 * y) * np.sin(9.8 * y)
def g_e(y):
amp = 0.66
return amp * np.exp(-2.5 * y_e) * np.sin(8.1 * y_e)
y = np.linspace(0, 0.83, 501)
y_e = np.linspace(0, 1.08, 501)
values = g(y)
values_e = g_e(y)
theta = np.radians(-65.9)
c, s = np.cos(theta), np.sin(theta)
rot_matrix = np.array(((c, s), (-s, c)))
xy = np.array([y, values]).T # rot_matrix
theta_e = np.radians(-60)
c_e, s_e = np.cos(theta_e), np.sin(theta_e)
rot_matrix_e = np.array(((c_e, s_e), (-s_e, c_e)))
xy_e = np.array([y, values_e]).T # rot_matrix_e
fig, ax = plt.subplots(figsize=(5, 5))
ax.axis('equal')
x_shift = 0.59
y_shift = 0.813
x_shift_e = 0.54
y_shift_e = 0.83
xf = np.concatenate([xy[:, 0] + x_shift, xy_e[::-1, 0] + x_shift_e])
yf = np.concatenate([xy[:, 1] + y_shift, xy_e[::-1, 1] + y_shift_e])
ax.plot(xy[:, 0] + x_shift, xy[:, 1] + y_shift, c='red')
ax.plot(xy_e[:, 0] + x_shift_e, xy_e[:, 1] + y_shift_e, c='black')
ax.fill(xf, yf, color='dodgerblue', alpha=0.3)
plt.show()

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:

Simulate stock price based on a given equation in Python

How can I generate a price time series using the following equation:
p(t) = p0(1+A * sin(ωt +0.5η(t)))
where t ranges from 0 to 1 in 1000 time steps, p0 = 100, A = 0.1, and ω = 100. η(t) is a sequence of i.i.d Gaussian random variables with zero mean and unit variance.
I have use the code as follows to generate price, but it seems not as required. So I need helps from the community. Thanks in advance.
from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt
mu = 0
sigma = 1
np.random.seed(2020)
dist = norm(loc = mu,scale=sigma)
sample = dist.rvs(size = 1000)
stock_price = np.exp(sample.cumsum())
print(stock_price)
plt.plot(stock_price)
plt.xlabel("Day")
plt.ylabel("Price")
plt.title("Simulated Stock price")
plt.show()
Assuming I haven't missed anything, this should do the trick
import numpy as np
import matplotlib.pyplot as plt
n_t = np.random.normal(0, 1, 1000)
t = np.arange(0, 1, 1/1000)
p_0, A, w = 100, 0.1, 100
ts = p_0 * (1 + A * np.sin(w * t + 0.5 * n_t))
plt.plot(t, ts)
plt.xlabel("Day")
plt.ylabel("Price")
plt.show()
which gives the plot
My trial, not sure if it's correct, welcome to give me some comments.
import numpy as np
import math
np.random.seed(2020)
mu = 0
sigma = 1
dt = 0.01
p0 = 100
A = 0.1
w = 100
N = 1000
for t in np.linspace(0, 1, 1000):
X = np.random.normal(mu * dt, sigma* np.sqrt(dt), N)
X = np.cumsum(X)
pt = p0 * (1+ A*np.sin(w*t + 0.5*X))
# print(pt)
plt.plot(pt)
plt.xlabel("Day")
plt.ylabel("Price")
plt.title("Simulated Stock price")
plt.show()
Out:

How to draw a semicircle using matplotlib

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)

Resources