How we can find the distance between two points inside a cluster? - python

I have to find the distance between two points inside the cluster. I have generated the clusters through the following code:
X = np.arange(0,10.2,0.16)
Y = np.arange(0,10.2,0.16)
A = np.arange(0,2, 0.005)
x, y = np.meshgrid(X, Y)
z = np.zeros(x.shape)
x0 = X.mean()
y0 = Y.mean()
b_center1 = [2,8]
b_center2 = [6,2]
r1=0.1*X.max()
r2=0.1*X.max()
for i in range(1, len(X)):
for j in range(1, len(Y)):
dist = pdist(np.array([[X[i],Y[j]],b_center1]))
if (dist[0] < r1):
z[i][j]=1
dist = pdist(np.array([[X[i],Y[j]],b_center2]))
if (dist[0] < r2):
z[i][j]=1
fig = plt.figure(figsize=(12,10))
plt.scatter(x, y, z, cmap='viridis', edgecolor='k')
plt.gca().set_aspect('equal', adjustable='box')
plt.draw()
plt.xticks([0,1,2,3,4,5,6,7,8,9,10])
plt.yticks([0,1,2,3,4,5,6,7,8,9,10])
plt.show()
This is the clusters I have obtained
d is the distance I have to find

Taking the z array, which is 64*64 matric with 0 and 1.
Get the x_index, y_index where z==1
np.where(z == 1)
(array([ 7, 7, 7, 7, 7, ...),
array([47, 48, 49, 50, 51, ...]))
So it can be seen, for x=7, z=1 for y=47, y=48, y=50 etc.
So we have to calculate the distance between (7,47) and (7,48)
So, the distance is Y[48] - Y[47] or Y[49] - Y[48]
print(Y[48] - Y[47])
>>> 0.15999999999999925 # i.e. around 0.16
And that is simply because you are line spacing by 0.16, your points are separated by 0.16, so you don't have to calculate at all. :p
X = np.arange(0,10.2,0.16)
Y = np.arange(0,10.2,0.16)
A = np.arange(0,2, 0.005)

Related

How to Create 3D Torus from Circle Revolved about x=2r, r is the radius of circle (Python or JULIA)

I need help to create a torus out of a circle by revolving it about x=2r, r is the radius of the circle.
I am open to either JULIA code or Python code. Whichever that can solve my problem the most efficient.
I have Julia code to plot circle and the x=2r as the axis of revolution.
using Plots, LaTeXStrings, Plots.PlotMeasures
gr()
θ = 0:0.1:2.1π
x = 0 .+ 2cos.(θ)
y = 0 .+ 2sin.(θ)
plot(x, y, label=L"x^{2} + y^{2} = a^{2}",
framestyle=:zerolines, legend=:outertop)
plot!([4], seriestype="vline", color=:green, label="x=2a")
I want to create a torus out of it, but unable, meanwhile I have solid of revolution Python code like this:
# Calculate the surface area of y = sqrt(r^2 - x^2)
# revolved about the x-axis
import matplotlib.pyplot as plt
import numpy as np
import sympy as sy
x = sy.Symbol("x", nonnegative=True)
r = sy.Symbol("r", nonnegative=True)
def f(x):
return sy.sqrt(r**2 - x**2)
def fd(x):
return sy.simplify(sy.diff(f(x), x))
def f2(x):
return sy.sqrt((1 + (fd(x)**2)))
def vx(x):
return 2*sy.pi*(f(x)*sy.sqrt(1 + (fd(x) ** 2)))
vxi = sy.Integral(vx(x), (x, -r, r))
vxf = vxi.simplify().doit()
vxn = vxf.evalf()
n = 100
fig = plt.figure(figsize=(14, 7))
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222, projection='3d')
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224, projection='3d')
# 1 is the starting point. The first 3 is the end point.
# The last 200 is the number of discretization points.
# help(np.linspace) to read its documentation.
x = np.linspace(1, 3, 200)
# Plot the circle
y = np.sqrt(2 ** 2 - x ** 2)
t = np.linspace(0, np.pi * 2, n)
xn = np.outer(x, np.cos(t))
yn = np.outer(x, np.sin(t))
zn = np.zeros_like(xn)
for i in range(len(x)):
zn[i:i + 1, :] = np.full_like(zn[0, :], y[i])
ax1.plot(x, y)
ax1.set_title("$f(x)$")
ax2.plot_surface(xn, yn, zn)
ax2.set_title("$f(x)$: Revolution around $y$")
# find the inverse of the function
y_inverse = x
x_inverse = np.power(2 ** 2 - y_inverse ** 2, 1 / 2)
xn_inverse = np.outer(x_inverse, np.cos(t))
yn_inverse = np.outer(x_inverse, np.sin(t))
zn_inverse = np.zeros_like(xn_inverse)
for i in range(len(x_inverse)):
zn_inverse[i:i + 1, :] = np.full_like(zn_inverse[0, :], y_inverse[i])
ax3.plot(x_inverse, y_inverse)
ax3.set_title("Inverse of $f(x)$")
ax4.plot_surface(xn_inverse, yn_inverse, zn_inverse)
ax4.set_title("$f(x)$: Revolution around $x$ \n Surface Area = {}".format(vxn))
plt.tight_layout()
plt.show()
Here is a way that actually allows rotating any figure in the XY plane around the Y axis.
"""
Rotation of a figure in the XY plane about the Y axis:
ϕ = angle of rotation
z' = z * cos(ϕ) - x * sin(ϕ)
x' = z * sin(ϕ) + x * cos(ϕ)
y' = y
"""
using Plots
# OP definition of the circle, but we put center at x, y of 4, 0
# for the torus, otherwise we get a bit of a sphere
θ = 0:0.1:2.1π
x = 4 .+ 2cos.(θ) # center at (s, 0, 0)
y = 0 .+ 2sin.(θ)
# add the original z values as 0
z = zeros(length(x))
plot(x, y, z, color=:red)
# add the rotation axis
ϕ = 0:0.1:π/2 # for full torus use 2π at stop of range
xprime, yprime, zprime = Float64[], Float64[], Float64[]
for a in ϕ, i in eachindex(θ)
push!(zprime, z[i] + z[i] * cos(a) - x[i] * sin(a))
push!(xprime, z[i] * sin(a) + x[i] * cos(a))
push!(yprime, y[i])
end
plot!(xprime, yprime, zprime, alpha=0.3, color=:green)
Here is a way using the Meshes package for the construction of the mesh and the MeshViz package for the visualization. You'll just have to translate to fulfill your desiderata.
using Meshes
using MeshViz
using LinearAlgebra
using GLMakie
# revolution of the polygon defined by (x,y) around the z-axis
# x and y have the same length
function revolution(x, y, n)
u_ = LinRange(0, 2*pi, n+1)[1:n]
j_ = 1:(length(x) - 1) # subtract 1 because of periodicity
function f(u, j)
return [x[j] * sin(u), x[j] * cos(u), y[j]]
end
points = [f(u, j) for u in u_ for j in j_]
topo = GridTopology((length(j_), n), (true, true))
return SimpleMesh(Meshes.Point.(points), topo)
end
# define the section to be rotated: a circle
R = 3 # major radius
r = 1 # minor radius
ntheta = 100
theta_ = LinRange(0, 2*pi, ntheta)
x = [R + r*cos(theta) for theta in theta_]
y = [r*sin(theta) for theta in theta_]
# make mesh
mesh = revolution(x, y, 100)
# visualize mesh
viz(mesh)
EDIT: animation
using Meshes
using MeshViz
using LinearAlgebra
using GLMakie
using Makie
using Printf
function revolutionTorus(R, r, alpha; n1=30, n2=90)
theta_ = LinRange(0, 2, n1+1)[1:n1]
x = [R + r*cospi(theta) for theta in theta_]
y = [r*sinpi(theta) for theta in theta_]
full = alpha == 2
u_ = LinRange(0, alpha, n2 + full)[1:n2]
function f(u, j)
return [x[j] * sinpi(u), x[j] * cospi(u), y[j]]
end
points = [f(u, j) for u in u_ for j in 1:n1]
topo = GridTopology((n1, n2 - !full), (true, full))
return SimpleMesh(Meshes.Point.(points), topo)
end
# generates `nframes` meshes for alpha = 0 -> 2 (alpha is a multiple of pi)
R = 3
r = 1
nframes = 10
alpha_ = LinRange(0, 2, nframes+1)[2:(nframes+1)]
meshes = [revolutionTorus(R, r, alpha) for alpha in alpha_]
# draw and save the frames in a loop
for i in 1:nframes
# make a bounding box in order that all frames have the same aspect
fig, ax, plt =
viz(Meshes.Box(Meshes.Point(-4.5, -4.5, -2.5), Meshes.Point(4.5, 4.5, 2.5)); alpha = 0)
ax.show_axis = false
viz!(meshes[i])
scale!(ax.scene, 1.8, 1.8, 1.8)
png = #sprintf "revolutionTorus%02d.png" i
Makie.save(png, fig)
end
# make GIF with ImageMagick
comm = #cmd "convert -delay 1x2 'revolutionTorus*.png' revolutionTorus.gif"
run(comm)

problem on generating more data points and plotting

I am able to plot the stair-step like plot as attached using the below code
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
x = np.array([3.45, 3.88, 3.99, 4.33])
y = np.array([14.0, 11.0, 14.0, 31.0])
y = np.cumsum(y)
y0 = np.array([0])
x0 = np.interp([0], y, x)
x = np.concatenate([x0, x])
y = np.concatenate([y0, y])
# Plot
fig, ax = plt.subplots()
ax.step(x, y, color='r', where='post')
ax.set_xlim(2, 5)
ax.set_ylim(0, y.max())
ax.invert_yaxis()
plt.show()
#####################################################
Now I need to generate more data points of x and y using interpolation function and want to generate same plot as above code produced(depicted above). I tried the below mentioned code but it produces different plot(depicted below), But definition says after interpolation, we should have the same plot, we just have more data points.
import numpy as np
from scipy.interpolate import interp1d
import matplotlib.pyplot as plt
x = np.array([3.45, 3.88, 3.99, 4.33])
y = np.array([14.0, 11.0, 14.0, 31.0])
y = np.cumsum(y)
y0 = np.array([0])
x0 = np.interp([0], y, x)
x = np.concatenate([x0, x])
y = np.concatenate([y0, y])
# I need to generate more data points
NUM = 100 # modify the number of points
funct = interp1d(x, y, kind='next')
x_cont = np.linspace(x[0], x[-1], NUM)
y_cont = funct(x_cont)
# Plot
fig, ax1 = plt.subplots()
ax1.step(x_cont, y_cont, color='r', where='post')
ax1.set_xlim(2, 5)
ax1.set_ylim(0, y.max())
ax1.invert_yaxis()
plt.show()
Update
IIUC, now you want the points where line changes direction. So you can use np.repeat
# Original data
x = np.array([3.45, 3.88, 3.99, 4.33])
y = np.array([14.0, 11.0, 14.0, 31.0])
y = np.cumsum(y)
# Find breakpoints
x_cont = np.hstack([x[0], np.repeat(x, 2)[1:]])
y_cont = np.hstack([0, np.repeat(y, 2)[:-1]])
# Plot
fig, ax = plt.subplots()
ax.scatter(x_cont, y_cont, marker='.', color='blue')
ax.plot(x_cont, y_cont, color='red')
ax.set_xlim(2, 5)
ax.set_ylim(0, y.max())
ax.invert_yaxis()
plt.show()
Output:
>>> x_cont
array([3.45, 3.45, 3.88, 3.88, 3.99, 3.99, 4.33, 4.33])
>>> y_cont
array([ 0., 14., 14., 25., 25., 39., 39., 70.])
Old answer
You want to increase the number of points for each step. You can use a custom function to interpolate values from (x1, y1) to (x2, y1) then from (x2, y1) to (x2, y2). It means you compute x points first then y. The function take 3 couple of parameters and the step size:
x, y: your intermediate step points (your two arrays x and y)
x0, y0: start coords (here you have to specify y=0 because it does not appear in your data)
xn, yn: end coords (here you can reuse the last value of x and y arrays)
step: the step size (we approximate the value to have points evenly spaced)
def interpolate(x, y, x0, y0, xn, yn, step):
# create arrays with all points
x = np.hstack([x0, x, xn])
y = np.hstack([y0, y, yn])
x_cont = []
y_cont = []
# get points pairwise
for x1, x2, y1, y2 in zip(x, x[1:], y, y[1:]):
# approximate the number of samples per segment
numx = int(np.abs(x2 - x1) / step)
numy = int(np.abs(y2 - y1) / step)
# x-first (left or right move)
a = np.linspace(x1, x2, numx, endpoint=False)
b = np.repeat(y1, numx)
# y-second (top or down move)
c = np.repeat(x2, numy)
d = np.linspace(y1, y2, numy, endpoint=False)
# save points
x_cont.append([*a, *c])
y_cont.append([*b, *d])
# flat all computed values
return np.hstack([*x_cont, xn]), np.hstack([*y_cont, yn])
# Original data
x = np.array([3.45, 3.88, 3.99, 4.33])
y = np.array([14.0, 11.0, 14.0, 31.0])
y = np.cumsum(y) # It seems you want the cumulative sum of y
x_cont, y_cont = interpolate(x, y, x[0], 0, x[-1], y[-1], step=0.1)
Plot the values:
fig, ax = plt.subplots()
ax.step(x_cont, y_cont, color='red', where='post')
ax.set_xlim(2, 5)
ax.set_ylim(0, y.max())
ax.invert_yaxis()
plt.show()
Output:
It seems like you are looking for a function that takes as input a number of pivots p and the number of points n to put in the horizontal and vertical straight lines connecting those pivots. I assume that you want the extra points to be evenly (linearly) spaced.
Essentially, you need to:
identify the pivot points
ensure the len(p) <= n
use repeated values for x and linearly spaced values for y when the lines are vertical
use repeated values for y and linearly spaced values for x when the lines are horizontal
A simple implementation using NumPy (and specifically np.linspace() and np.repeat()) could be:
import typing as typ
import numpy as np
def upscale_steps_equi(
p_x: typ.Sequence[float],
p_y: typ.Sequence[float],
n: int,
start_hor: typ.Optional[str] = None,
dtype: np.dtype = np.float_,
):
"""
The points are equi-spaced (except near the pivots).
The pivots are, in general, not included.
Args:
p_x: Must be strictly monotonic increasing.
p_y: Must be strictly monotonic increasing.
n: Must be larger than max(len(p_x), len(p_y))
start_hor: Must be True for horizontal, False for vertical.
Only used (and needed) if len(p_x) == len(p_y)
"""
p_x_n = len(p_x)
p_y_n = len(p_y)
is_same_len = p_x_n == p_y_n
p_n = max(p_x_n, p_y_n) + 1 # number of points
if p_x_n > p_y_n:
start_hor = True
elif p_x_n < p_y_n:
start_hor = False
elif start_hor is None or not isinstance(start_hor, bool):
raise ValueError("`start_hor` required if len(p_x) == len(p_y)")
p_x_ = np.repeat(p_x, 2) # x-coords of pivots
p_y_ = np.repeat(p_y, 2) # y-coords of pivots
if is_same_len:
if start_hor:
p_x_ = p_x_[1:]
p_y_ = p_y_[:-1]
else:
p_x_ = p_x_[:-1]
p_y_ = p_y_[1:]
else:
if start_hor:
p_x_ = p_x_[1:-1]
else:
p_y_ = p_y_[1:-1]
dx = max(p_x) - min(p_x) # distance covered along x
dy = max(p_y) - min(p_y) # distance covered along y
d = dx + dy
ll = np.linspace(0, d, n, endpoint=True)
x = min(p_x) + ll
y = min(p_y) + ll
last_x_ = last_y_ = last_d_ = None
d_ = d_x_ = d_y_ = 0
for x_, y_ in zip(p_x_, p_y_):
if x_ == last_x_:
dd_y_ = y_ - last_y_
d_y_ += dd_y_
d_ += dd_y_
mask = (ll >= last_d_) & (ll < d_)
x[mask] = x_
y[mask] -= d_x_
elif y_ == last_y_:
dd_x_ = x_ - last_x_
d_x_ += dd_x_
d_ += dd_x_
mask = (ll >= last_d_) & (ll < d_)
y[mask] = y_
x[mask] -= d_y_
last_x_ = x_
last_y_ = y_
last_d_ = d_
x[-1] = p_x[-1]
y[-1] = p_y[-1]
return x, y
to be used like:
import matplotlib.pyplot as plt
x, y = upscale_steps_equi([1, 4, 5], [2, 3, 7, 9], 20)
plt.scatter(x, y, marker='o')
plt.axis('scaled')
The function above does not, in general, include the pivots.
However, if the pivots must be included, one needs to forego the exact number of points and the same spacing for x and y.
Here is a possible solution where the points are equi-spaced within each segment:
import typing as typ
import numpy as np
def upscale_steps_with_pivots(
p_x: typ.Sequence[float],
p_y: typ.Sequence[float],
n: int,
start_hor: typ.Optional[bool] = None,
dtype: np.dtype = np.float_,
):
"""
The points are equi-spaced only within each segment.
The pivots are strictly included.
Args:
p_x: Must be strictly monotonic increasing.
p_y: Must be strictly monotonic increasing.
n: Must be larger than max(len(p_x), len(p_y))
start_hor: Must be `h` for horizontal, `v` for vertical.
Only used (and needed) if len(p_x) == len(p_y)
"""
p_x_n = len(p_x)
p_y_n = len(p_y)
is_same_len = p_x_n == p_y_n
p_n = max(p_x_n, p_y_n) + 1 # number of points
if p_x_n > p_y_n:
start_hor = True
elif p_x_n < p_y_n:
start_hor = False
elif start_hor is None or not isinstance(start_hor, bool):
raise ValueError("`start_hor` required if len(p_x) == len(p_y)")
p_x_ = np.repeat(p_x, 2) # x-coords of pivots
p_y_ = np.repeat(p_y, 2) # y-coords of pivots
if is_same_len:
if start_hor:
p_x_ = p_x_[1:]
p_y_ = p_y_[:-1]
else:
p_x_ = p_x_[:-1]
p_y_ = p_y_[1:]
else:
if start_hor:
p_x_ = p_x_[1:-1]
else:
p_y_ = p_y_[1:-1]
dx = max(p_x) - min(p_x) # distance covered along x
dy = max(p_y) - min(p_y) # distance covered along y
d = dx + dy
n_x = (np.diff(p_x) / d * (n - p_n)).astype(np.int_)
n_y = (np.diff(p_y) / d * (n - p_n)).astype(np.int_)
r = np.ones(len(n_x) + len(n_y) + 1, dtype=np.int_)
if start_hor:
r[:-1 if is_same_len else None:2] = n_x + 1
r[1:-1:2] = n_y + 1
else:
r[:-1 if is_same_len else None:2] = n_y + 1
r[1:-1:2] = n_x + 1
x = np.repeat(p_x_, r).astype(dtype)
y = np.repeat(p_y_, r).astype(dtype)
j = 0
for i, r_ in enumerate(r[:-1]):
if i % 2 != start_hor:
k = np.linspace(p_x_[i], p_x_[i + 1], r_, endpoint=False)
x[j : j + len(k)] = k
else:
k = np.linspace(p_y_[i], p_y_[i + 1], r_, endpoint=False)
y[j : j + len(k)] = k
j += r_
return x, y
to be used like:
import matplotlib.pyplot as plt
x, y = upscale_steps_with_pivots([1, 4, 5], [2, 3, 7, 9], 20)
plt.scatter(x, y, marker='o')
plt.axis('scaled')
(Note that until the computation of d, the two functions are identical, and it mostly contain the logic to deal with the different possible configurations of segments.)
This line
funct = interp1d(x, y, kind='next')
needs to be changed in
funct = interp1d(x, y, kind='previous')
This because you want values in [3.99, 4.33] (e.g.) to refer to the cumsum-value of 3.99, which is ~40 (previous) instead of values related to 4.33 which is ~70 (next).

System blows up when trying to optimise vehicle movement using control package

I am attempting to optimise the movement of a vehicle from position A to position B. I have tried copying the code from the documentation, but it does not work when I paste it.
This is my code so far:
import numpy as np
import control as ct
import control.optimal as opt
import matplotlib.pyplot as plt
def vehicle_update(t, x, u, params):
# Get the parameters for the model
l = params.get('wheelbase', 3.) # vehicle wheelbase (m)
phimax = params.get('maxsteer', 0.5) # max steering angle (rad)
# Saturate the steering input
phi = np.clip(u[1], -phimax, phimax)
# Return the derivative of the state
return np.array([
np.cos(x[2]) * u[0], # xdot = cos(theta) v
np.sin(x[2]) * u[0], # ydot = sin(theta) v
(u[0] / l) * np.tan(phi) # thdot = v/l tan(phi)
])
def vehicle_output(t, x, u, params):
return x # return x, y, theta (full state)
# Define the vehicle steering dynamics as an input/output system
vehicle = ct.NonlinearIOSystem(
vehicle_update, vehicle_output, states=3, name='vehicle',
inputs=('v', 'phi'), outputs=('x', 'y', 'theta'))
#We consider an optimal control problem that consists of “changing lanes” by moving from the point x = 0 m, y = -2 m, \theta = 0 to the point x = 100 m, y = 2 m, \theta = 0) over a period of 10 seconds and with a with a starting and ending velocity of 10 m/s:
x0 = [0, -2, 0]; u0 = [10, 0]
xf = [100, 2, 0]; uf = [10, 0]
Tf = 10
#To set up the optimal control problem we design a cost function that penalizes the state and input using quadratic cost functions:
Q = np.diag([0.1, 10, 0.1]) # keep lateral error low
R = np.eye(2) * 0.1
cost = opt.quadratic_cost(vehicle, Q, R, x0=xf, u0=uf)
#We also constraint the maximum turning rate to 0.1 radians (about 6 degees) and constrain the velocity to be in the range of 9 m/s to 11 m/s:
constraints = [ opt.input_range_constraint(vehicle, [8, -0.1], [11, 0.1]) ]
#Finally, we solve for the optimal inputs:
horizon = np.linspace(0, Tf, 20, endpoint=True)
bend_left = [10, 0.01] # slight left veer
result = opt.solve_ocp(
vehicle, horizon, x0, cost, constraints, initial_guess=bend_left,
options={'eps': 0.01}) # set step size for gradient calculation
# Extract the results
u = result.inputs
t, y = ct.input_output_response(vehicle, horizon, u, x0)
#Plotting the results:
Norows = 3
Nocols = 1
width = 10
height = 10
fig, axes = plt.subplots(nrows=Norows, ncols=Nocols, figsize=(width, height)) #Graph Layout
# Plot the results
plt.subplot(Norows, Nocols, 1)
plt.plot(y[0], y[1])
plt.plot(x0[0], x0[1], 'ro', xf[0], xf[1], 'ro')
plt.xlabel("x [m]")
plt.ylabel("y [m]")
plt.subplot(Norows, Nocols, 2)
plt.plot(t, u[0])
plt.axis([0, 10, 8.5, 11.5])
plt.plot([0, 10], [9, 9], 'k--', [0, 10], [11, 11], 'k--')
plt.xlabel("t [sec]")
plt.ylabel("u1 [m/s]")
plt.subplot(Norows, Nocols, 3)
plt.plot(t, u[1])
plt.axis([0, 10, -0.15, 0.15])
plt.plot([0, 10], [-0.1, -0.1], 'k--', [0, 10], [0.1, 0.1], 'k--')
plt.xlabel("t [sec]")
plt.ylabel("u2 [rad/s]")
plt.suptitle("Lane change manoeuvre")
plt.tight_layout()
plt.show()
Despite the effort, the system appears to blow up, as shown in the first graph when running the code.

Length of the entire tan() function cut off by two lines in Python?

My code:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
y = np.tan(x)
y2 = 4 + x*0
y3 = -4 + x*0
fig = plt.figure(figsize=(8,5))
ax = fig.add_subplot(111)
diffs = np.sqrt(np.diff(x)**2+np.diff(y)**2)
length = diffs.sum()
numbers = [2, 4, 6, 8, 10]
p2 = []
for i in range(len(numbers)):
cumlenth = np.cumsum(diffs)
s = np.abs(np.diff(np.sign(cumlenth-numbers[i]))).astype(bool)
c = np.argwhere(s)[0][0]
p = x[c], y[c]
p2.append(p)
ax.cla()
ax = fig.add_subplot(111)
for j in range(len(p2)):
ax.scatter(p2[j][0],p2[j][1], color="crimson", s=5)
plt.plot(np.tan(x))
plt.plot(y2)
plt.plot(y3)
plt.ylim(-10, 10)
I'm trying to find the length of the tan() function cut off by two lines y2, y3 in a certain compartment. This means that only the part marked in red below should be taken to the total length of the chart:
Next, I try to mark the position of a points from list numbers = [] on this the graph, which are lying in the distance equal to the value of these points, starting from the beginning of the graph in point (x,y)=(0,0), and I want get their coordinates. Which for my sample list numbers = [] would give something like this:
What am I missing? Can this be achieved?
I will be grateful for any tips.
plt.plot takes two arguments, an x array and a y array; without providing both, pyplot assumes that you wanted to plot them against the index of the value in the array. So, your first hurdle is to change the lines at the bottom to:
plt.plot(x, np.tan(x))
plt.plot(x, y2)
plt.plot(x, y3)
Now we have the issue of the fact that your calculation is taking the whole graph into account, not just the parts between -4 and 4. You could solve this by filtering the x array by your thresholds:
x_all = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
x_above = x_all[ -4 < np.tan(x_all) ]
x = x_above[ np.tan(x_above) < 4 ]
Finally, we have the issue that the diff calculation seems to be taking the jump from +4 to -4 into account. We can mitigate this by filtering out anywhere the diff in y is negative:
y_up = np.diff(y) > 0
y_diff = np.where( y_up, np.diff(y), 0 )
x_diff = np.where( y_up, np.diff(x), 0 )
diffs = np.sqrt( x_diff**2 + y_diff**2 )
My final code looks like this, and seems to be working as you expect it to:
import matplotlib.pyplot as plt
import numpy as np
x_all = np.linspace(-2 * np.pi, 2 * np.pi, 1000)
x_above = x_all[ -4 < np.tan(x_all) ]
x = x_above[ np.tan(x_above) < 4 ]
y = np.tan(x)
y2 = 4 + x*0
y3 = -4 + x*0
y_up = np.diff(y) > 0
y_diff = np.where( y_up, np.diff(y), 0 )
x_diff = np.where( y_up, np.diff(x), 0 )
diffs = np.sqrt( x_diff**2 + y_diff**2 )
length = diffs.sum()
numbers = [2, 4, 6, 8, 10]
p2 = []
for i in range(len(numbers)):
cumlenth = np.cumsum(diffs)
s = np.abs(np.diff(np.sign(cumlenth-numbers[i]))).astype(bool)
c = np.argwhere(s)[0][0]
p = x[c], y[c]
p2.append(p)
for j in range(len(p2)):
plt.scatter( p2[j][0], p2[j][1], color="crimson", s=5)
plt.plot(x, np.tan(x))
plt.plot(x, y2)
plt.plot(x, y3)
plt.ylim(-10, 10)
plt.show()

Logistic regression: plotting decision boundary from theta

I have the following code:
x1 = np.random.randn(100)
y1 = np.random.randn(100) + 3
x2 = np.random.randn(100) + 3
y2 = np.random.randn(100)
plt.plot(x1, y1, "+", x2, y2, "x")
plt.axis('equal')
plt.show()
which results in the following image
I have implemented my own logistic regression, and this returns a theta, and I want to use this theta to plot the decision boundary, but I'm not sure how to do this.
X = np.matrix(np.vstack((np.hstack((x1,x2)), np.hstack((y1,y2)))).T)
X = np.concatenate((np.ones((X.shape[0], 1)), X), axis=1)
Y = np.matrix(1.0 * np.hstack((np.zeros(100), np.ones(100)))).T
learning_rate = 0.0001
iterations = 3000
theta = np.matrix([[0.5], [0.5], [0.5]])
theta = logistic_regression(theta, X, Y, learning_rate, iterations)
and this gives theta =
[[ 0.40377942]
[ 0.53696461]
[ 0.1398419 ]]
for example. How can I use this to plot the decision boundary?
You want to plot θTX = 0, where X is the vector containing (1, x, y). That is, you want to plot the line defined by theta[0] + theta[1]*x + theta[2]*y = 0. Solve for y:
y = -(theta[0] + theta[1]*x)/theta[2]
So, something like:
theta = theta[:,0] # Make theta a 1-d array.
x = np.linspace(-6, 6, 50)
y = -(theta[0] + theta[1]*x)/theta[2]
plt.plot(x, y)
Something doesn't look right, though, because you have theta[1] > 0 and theta[2] > 0, which results in a line with a negative slope.

Categories