Construct a smooth curve from mouse coordinates - python

In a project I'm working on, i get mouse coordinates every X milliseconds. I would like to draw the most likely path between these coordinates.
By example :
- After X ms, i could get these (x,y) coordinates : (0, 0), (3, 1), (5, 4), (6, 7)
- After 2*X ms i could have this : (0, 0), (3, 1), (5, 4), (6, 7), (8, 5), (11, -7)
- etc.
I would like to draw step by step a path between these points, once I've drawn a path i can't change it (i can't wait to have all the coordinates to draw the line).
I started to think about a solution where I draw lines between pair of coordinates by calculating a polynomial fit:
import numpy as np
import matplotlib.pyplot as plt
def construct_path(points):
x = points[:,0]
y = points[:,1]
(x_new,y_new) = ([],[])
for i in range(0,len(x) - 2):
(x_tmp, y_tmp) = get_new_points(x[i:(i+3)], y[i:(i+3)], (i+3) == len(x))
(x_new,y_new) = (x_new + x_tmp.tolist(), y_new + y_tmp.tolist())
previous_points = [x_tmp,y_tmp]
return (x_new, y_new)
def get_new_points(x,y, end):
x = np.array(x)
y = np.array(y)
# calculate polynomial
z = np.polyfit(x, y, 2)
f = np.poly1d(z)
# calculate new x's and y's
if not end:
x_new = np.linspace(x[0], x[1], 11)
else:
x_new = np.linspace(x[0], x[1], 10, endpoint=False).tolist() + np.linspace(x[1], x[2], 11).tolist()
x_new = np.array(x_new)
y_new = f(x_new)
print(x_new, y_new)
return (x_new, y_new)
points = np.array([(0, 0), (3, 1), (5, 4), (6, 7), (8, 5), (11, -7) ])
x = points[:,0]
y = points[:,1]
(x_new, y_new) = construct_path(points)
plt.plot(x,y,'o',np.array(x_new),np.array(y_new))
plt.xlim([-2, 12])
plt.ylim([-10, 10])
plt.show()
The result is ok :
But it doesn't work when points have close x's or y's (ex : (0, 0), (3, 1), (5.8, 4), (6, 7), (8, 5), (11, -7))
EDIT : found some interesting leads :
from __future__ import division
import numpy as np
import matplotlib.pyplot as plt
import scipy.interpolate
def range_spline(x,y):
t = np.arange(x.shape[0], dtype=float)
t /= t[-1]
nt = np.linspace(0, 1, 100)
new_x = scipy.interpolate.spline(t, x, nt)
new_y = scipy.interpolate.spline(t, y, nt)
return (new_x,new_y)
def dist_spline(x,y):
t = np.zeros(x.shape)
t[1:] = np.sqrt((x[1:] - x[:-1])**2 + (y[1:] - y[:-1])**2)
t = np.cumsum(t)
t /= t[-1]
nt = np.linspace(0, 1, 100)
new_x = scipy.interpolate.spline(t, x, nt)
new_y = scipy.interpolate.spline(t, y, nt)
return (new_x, new_y)
x = np.array([ 0, 3, 6, 6, 8, 11, 8, 6, 6])
y = np.array([ 0, 1, 4, 7, 5, -7, -10, -10, -5])
#x = np.array([ 0, 2, 4])
#y = np.array([ 0, 2, 0])
(x1, y1) = range_spline(x,y)
(x2,y2) = dist_spline(x,y)
plt.plot(x,y, 'o')
plt.plot(x1, y1, label='range_spline')
plt.plot(x2, y2, label='dist_spline')
plt.legend(loc='best')
plt.show()
It works well when there are many points :
But not so well when there are less than 5 points (which is what i'd like) :

Related

Adding circle to a plot results in a 2nd scale on the axis and nothing being displayed on the plot

Once I attempt to add circles to the plot nothing displays on the plot.
Without the circle code, the x and y axis scale has major grid lines 2,3,4,5,6,7,8, and the data displays.
Once I add the circle code it appears the 2nd scale of 0 to 1.0 is added to both axis.
I believe this is why the plot is blank. No data has a value between 0 and 1.
Not sure why the 2nd axis scale is being added.
import matplotlib.pyplot as plt
import matplotlib.path
from matplotlib.patches import Circle
sample = (5, 5)
circles = [(2, 8), (4, 6), (5, 7)]
squares = [(4, 2), (6, 2), (6, 4)]
plt.figure("Concept", (5, 5))
plt.set_cmap('gray')
# plt.axis((0, 10, 0, 10), option='equal')
plt.axis('equal')
plt.scatter(*sample, marker="D", label="??", color='0.0')
plt.scatter([x for x, y in circles], [y for x, y in circles], marker="o", color='.20')
plt.scatter([x for x, y in squares], [y for x, y in squares], marker="s", color='.33')
# k = 3 nearest neighbors
circle3 = Circle((5, 5), 2, facecolor='none',
edgecolor='black', linestyle='--', alpha=0.8)
plt.axes().add_patch(circle3)
# k = 5 nearest neighbors
circle5 = Circle((5, 5), 3.2, facecolor='none',
edgecolor='black', linestyle=':', alpha=1.0)
plt.axes().add_patch(circle5)
plt.grid(True)
plt.show()

Contour Plot of the Gradient Descent Algorithm in Python

I'm trying to apply gradient descent to a simple linear regression model, when plotting a 2D graph I get the intended result but when I switch into a contour plot I don't the intended plot, I would like to know where my mistake is.
Here is the code:
def J(b_0, b_1, x, y):
return (1/len(y))*(y - b_0 - b_1*x)**2
def dJ_1(b_0, b_1, x, y):
return (2/len(y))*np.sum(x*(b_1*x + b_0 - y))
def dJ_0(b_0, b_1, x, y):
return (2/100)*np.sum((b_1*x + b_0 - y))
x = np.linspace(-1, 1, 100)
y = np.linspace(-2, 2, 100)
b_0 = 5
b_1 = 5
parameters_0 = [b_0]
parameters_1 = [b_1]
for i in range(99):
b_1 -= 0.1*dJ_1(b_0, b_1, x, y)
b_0 -= 0.1*dJ_0(b_0, b_1, x, y)
parameters_0.append(b_0)
parameters_1.append(b_1)
plt.figure(figsize=(4, 8))
plt.plot(np.linspace(-2, 7, 100), J(np.linspace(-2, 7, 100), parameters_1[-1], -1, -2))
plt.plot(np.array(parameters_0), J(np.array(parameters_0), parameters_1[-1], -1, -2), color="C1")
plt.plot(np.array(parameters_0), J(np.array(parameters_0), parameters_1[-1], -1, -2), '-o', color="C1")
plt.xlabel(r"$\beta_0$")
plt.ylabel(r"$J(\beta_0)$")
plt.show()
The first plot:
plt.figure(figsize=(4, 8))
plt.plot(np.linspace(-4, 7, 100), J(parameters_0[-1], np.linspace(-4, 7, 100), -1, -2))
plt.plot(np.array(parameters_1), J(parameters_0[-1], np.array(parameters_1), -1, -2), color="C1")
plt.plot(np.array(parameters_1), J(parameters_0[-1], np.array(parameters_1), -1, -2), '-o', color="C1")
plt.xlabel(r"$\beta_1$")
plt.ylabel(r"$J(\beta_1)$")
plt.show()
The second plot:
b_0 = np.linspace(-10, 10, 100)
b_1 = np.linspace(-10, 10, 100)
X, Y = np.meshgrid(b_0, b_1)
Z = J(X, Y, x=-1, y=-2)
fig,ax=plt.subplots(1,1)
cp = ax.contourf(X, Y, Z)
fig.colorbar(cp)
ax.set_xlabel(r"$\beta_0$")
ax.set_ylabel(r"$\beta_1$")
plt.show()
The contour plot is:
Why do I get the above plot rather than a plot similar to this below one for example when the global minima of the cost function is at (0, 2)? Thanks in advance.
Well I think there's no mistake there, you can see from the 2d plot that your gradient descent plot is a quadratic function, thus the way you see it from the contour is as if you see it from the sky to the valley. As to why it doesn't look like a circle, well it's because it's just a 3d quadratic function. I also once made something similar, and the gradient descent plot is just as what you plot. Check it out here at the end of the page

How can I plot an ellipse over different centers defined in an array

I am plotting an ellipse and the translating it using the translate function where are define manually dx & dy
Now I would like to have more plots with different values of dx,dy which are contained in this array.
translation_points =
[ (5, 6), (5, 7), (5, 8), (5, 9), (5, 10), (5, 11), (5, 12), (5, 13), (5, 14), (6, 5), (6, 6), (6, 7), (6, 8), (6, 9), (6, 10), (6, 11), (6, 12), (6, 13), (6, 14), (7, 5), (7, 6), (7, 7), (7, 8), (7, 9), (7, 10), (7, 11), (7, 12)]
How can I do that?
import numpy as np
import matplotlib.pyplot as plt
def ellipse(x, y):
value = (x*x) + (y*y)/3
if (value >= 300):
return 0
else:
return 1
def translate(x, y):
DX = 5
DY = 5
return (x- DX, y - DY)
def rotate(x, y):
theta = np.radians(40)
matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
return np.dot(matrix, (x,y))
data = np.zeros((100,100))
for i in range(0, 100):
for j in range(0, 100):
(x, y) = translate(i,j)
(x, y) = rotate(x, y)
data[i,j] = ellipse(x, y)
plt.imshow(data, cmap="gray")
plt.show()
import numpy as np
import matplotlib.pyplot as plt
translation_points = [ (5, 6), (5, 7), (10,10), (20, 8), (5, 9), (12, 10), (40, 40), (50, 50),(20, 8)]
def ellipse(x, y):
value = (x*x) + (y*y)/3
if (value >= 300):
return 0
else:
return 1
def translate(x, y,a,b):
#print a,b
DX = a
DY = b
return (x- DX, y - DY)
def rotate(x, y):
theta = np.radians(40)
matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
return np.dot(matrix, (x,y))
def create(tlpoints):
a,b=tlpoints
#print a,b
data = np.zeros((100,100))
for i in range(0, 100):
for j in range(0, 100):
(x, y) = translate(i,j,a,b)
(x, y) = rotate(x, y)
data[i,j] = ellipse(x, y)
return data
ells=[create(translation_points[i]) for i in range(len(translation_points))]
fig=plt.figure(figsize=(10,10))
columns = 3
rows = len(translation_points)/columns
for i in range(1, columns*rows +1):
fig.add_subplot(rows, columns, i)
plt.imshow(ells[i-1],cmap='gray')
plt.show()
first, modify your translate(), add a new parameter offset:
def translate(x, y, offset):
(dx, dy) = offset
return x - dx, y - dy
then put the 2 for loops in a function so we can call it later, this function should accept a parameter offset too. then we can call it to plot for each offset.
def draw(offset):
data = np.zeros((100, 100))
for i in range(-100, 100):
for j in range(-100, 100):
(x, y) = translate(i, j, offset)
(x, y) = rotate(x, y)
data[i, j] = ellipse(x, y)
plt.imshow(data, cmap="gray")
finally, create a loop that plot our ellipse for each offset in translation_points. here i use plt.subplot(4, 7, i+1) to create 28 subplots, each subplots is for a translated ellipse. you can comment this line if you just want to see each separate plot.
for i in range(len(translation_points)):
plt.subplot(4, 7, i+1)
draw(translation_points[i])
yeah, we did it.
more edit:
since we use imshow, the plots are cropped. moreover, the coordinates are totally wrong. so first set our range:
for i in range(-100, 100):
for j in range(-100, 100):
then give it some default offset:
def translate(x, y, offset):
(dx, dy) = offset
return x - dx - 50, y - dy - 50
extend the figure, set axis limits: add these lines in draw()
plt.xlim(-50, 50)
plt.ylim(-50, 50)
plt.imshow(data, cmap="cool", extent=[-data.shape[1]/2., data.shape[1]/2., -data.shape[0]/2., data.shape[0]/2.])
and finally:
import numpy as np
import matplotlib.pyplot as plt
translation_points = [(5, 6), (5, 7), (5, 8), (5, 9), (5, 10), (5, 11),
(5, 12), (5, 13), (5, 14), (6, 5), (6, 6), (6, 7),
(6, 8), (6, 9), (6, 10), (6, 11), (6, 12), (6, 13),
(6, 14), (7, 5), (7, 6), (7, 7), (7, 8), (7, 9),
(7, 10), (7, 11), (7, 12)]
def ellipse(x, y):
value = (x*x) + (y*y)/3
if value >= 300:
return 0
else:
return 1
def translate(x, y, offset):
# dx = 5
# dy = 5
(dx, dy) = offset
return x - dx - 50, y - dy - 50
def rotate(x, y):
theta = np.radians(40)
matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])
return np.dot(matrix, (x, y))
def draw(offset):
data = np.zeros((100, 100))
for i in range(-100, 100):
for j in range(-100, 100):
(x, y) = translate(i, j, offset)
(x, y) = rotate(x, y)
data[i, j] = ellipse(x, y)
plt.xlim(-50, 50)
plt.ylim(-50, 50)
plt.imshow(data, cmap="gray",
extent=[-data.shape[1]/2., data.shape[1]/2.,
-data.shape[0]/2., data.shape[0]/2.])
for i in range(len(translation_points)):
plt.subplot(4, 7, i+1)
draw(translation_points[i])
plt.show()

why does my pyplot show no lines?

I am new to pyplot and wondering what I'm doing wrong here.
I would like to plot a series of random line segments:
Here's some example code:
import matplotlib.pyplot as plt
def testPlot():
minx = miny = -1
maxx = maxy = 30
# some points randomly generated
points = [((10, 21), (19, 22)), ((11, 9), (22, 27)), ((9, 13), (5, 9)), ((18, 4), (2, 21)), ((25, 27
for pair in points:
print pair
for point in pair: #plot each point with a small dot
x = point[0]
y = point[1]
plt.plot(x,y,'bo')
# draw a line between the pairs of points
plt.plot(pair[0][0],pair[0][1],pair[1][0],pair[1][1],color='r',linewidth=2)
plt.axis([minx,maxx,miny,maxy])
plt.show()
Here is what I get after running that, there should be lines between the points but where are the lines?
((10, 21), (19, 22))
((11, 9), (22, 27))
((9, 13), (5, 9))
((18, 4), (2, 21))
((25, 27), (11, 13))
Thank you for any clues
This is the line of problem:
...
plt.plot(pair[0][0],pair[0][1],pair[1][0],pair[1][1],color='r',linewidth=2)
...
You're trying to draw the referring to x,y,x1,y1, which in fact should be ((x, x1), (y, y1)). Correcting this seems working fine:
def testPlot():
minx = miny = -1
maxx = maxy = 30
# some points randomly generated
points = [((10, 21), (19, 22)), ((11, 9), (22, 27)), ((9, 13), (5, 9)), ((18, 4), (2, 21)), ((25, 27), (11, 13))]
for pair in points:
print pair
for point in pair: #plot each point with a small dot
x = point[0]
y = point[1]
plt.plot(x,y,'bo')
# change this line to ((x, x1), (y, y1))
plt.plot((pair[0][0],pair[1][0]),(pair[0][1],pair[1][1]), color='r',linewidth=2)
plt.axis([minx,maxx,miny,maxy])
plt.show()
Results:

Add points to scatterplot and plot a colorbar beside it in python

I have successfully created a scatter plot where each point has a x coordinate, y coordinate and a third variable (e.g., time) that I represent using a color bar. All points that have time value within [0,100] are correctly represented. However, sometimes time takes the value float('inf'). The color bar ignores such points, I want to superimpose these onto the scatter plot. How can I make this addition?
import random
import pylab
x1 = [random.randint(1,11) for x1_20times in range(20)]
y1 = [random.randint(1,11) for y1_20times in range(20)]
time1 = [random.randint(1,12) for time1_20times in range(20)]
x2 = [random.randint(1,11) for x1_20times in range(20)]
y2 = [random.randint(1,11) for y1_20times in range(20)]
time2 = [random.randint(1,100) for time1_20times in range(20)]
time2[5:8] = [float('inf')]*3 # Change a few of the entries to infinity.
pylab.subplot(2,1,1)
pylab.scatter(x1, y1, c = time1, s = 75)
pylab.xlabel('x1')
pylab.ylabel('y1')
pylab.jet()
pylab.colorbar()
pylab.subplot(2,1,2)
pylab.scatter(x2, y2, c = time2, s = 75)
pylab.scatter(x2[5:8], y2[5:8], s = 75, marker = ur'$\mathcircled{s}$')
pylab.xlabel('x2')
pylab.ylabel('y2')
# m2 = pylab.cm.ScalarMappable(cmap = pylab.cm.jet)
# m2.set_array(time2)
# pylab.colorbar(m2)
# pylab.tight_layout()
pylab.show()
I can get the points to correctly plot (and I am assuming the color representation is also accurate) but the I can't display the colorbar for the second subplot beside the scatterplot.
Extract out the points:
In [25]: filter(lambda m: m[2] == float('inf'), zip(x2, y2, time2))
Out[25]: [(4, 6, inf), (9, 6, inf), (2, 2, inf)]
In [26]: zip(*filter(lambda m: m[2] == float('inf'), zip(x2, y2, time2)))
Out[26]: [(4, 9, 2), (6, 6, 2), (inf, inf, inf)]
In [27]: x,y,t = zip(*filter(lambda m: m[2] == float('inf'), zip(x2, y2, time2)))
and plot them however you like:
pylab.plot(x, y, 's', mfc='black', mec='None', ms=7)

Categories