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:
Related
I have the following list and I like to make a histogramm out of that data but i dont know how to do it.
finished = [('https', 38), ('on', 33), ('with', 32), ('model', 28), ('com', 26), ('evaluation', 19), ('detection', 19), ('br', 18), ('models', 18), ("href='g3doc", 17), ('trained', 17)]
I have tried the following:
import matplotlib.pyplot as plt
z=0
for i in finished:
plt.hist(finished[z], bins = range(38))
z=z+1
plt.show()
Im always confused regarding the labels and the values.
Thank you and have a nice day
I would use a bar chart like so:
import matplotlib.pyplot as plt; plt.rcdefaults()
import numpy as np
import matplotlib.pyplot as plt
finished = [('https', 38), ('on', 33), ('with', 32), ('model', 28), ('com', 26), ('evaluation', 19), ('detection', 19), ('br', 18), ('models', 18), ("href='g3doc", 17), ('trained', 17)]
names = list(f[0] for f in finished)
values = list(f[1] for f in finished)
y_pos = np.arange(len(finished))
plt.figure(figsize=(20,10))
plt.bar(y_pos, values, align='center', alpha=0.5)
plt.xticks(y_pos, names)
plt.ylabel('Values')
plt.title('Word usage')
plt.show()
You may be better off with a different format for your data. But this works with your sample data.
As suggested in the comments, you want to create a bar chart
import pandas as pd
import matplotlib.pyplot as plt
finished = [('https', 38), ('on', 33), ('with', 32), ('model', 28), ('com', 26), ('evaluation', 19), ('detection', 19), ('br', 18), ('models', 18), ("href='g3doc", 17), ('trained', 17)]
df = pd.DataFrame(finished)
ax = df.plot(kind="bar")
ax.set_xticklabels(list(df.iloc[:,0].values))
plt.xticks(rotation=90)
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()
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) :
This is my plot.
I need to show the legend for the different colors used.
How do I do that?
My code for the plot:
def mscatter(p, x, y, c,typestr,source):
p.scatter(x, y, marker=typestr,
line_color="#6666ee", fill_color=c, fill_alpha=0.5, size=y*1.5,source = source)
p = figure(title="CGPA of 4th year students",tools=[hover])
mscatter(p, xdata, ydata, colors,"circle",source)
show(p)
here is sample bokeh documentation on adding legends
You will have to modify as you see fit
from collections import OrderedDict
from bokeh.charts import Scatter, output_file, show
# (dict, OrderedDict, lists, arrays and DataFrames of (x, y) tuples are valid inputs)
xyvalues = OrderedDict()
xyvalues['python'] = [(1, 2), (3, 3), (4, 7), (5, 5), (8, 26)]
xyvalues['pypy'] = [(1, 12), (2, 23), (4, 47), (5, 15), (8, 46)]
xyvalues['jython'] = [(1, 22), (2, 43), (4, 10), (6, 25), (8, 26)]
scatter = Scatter(xyvalues, title="Scatter", legend="top_left", ylabel='Languages')
output_file('scatter.html')
show(scatter)
the above code will result in the following picture:
I have a polygon comprising of 5 edges. Each edge has its own width, which is randomly generated between 0.2 and 0.5 here for illustration purpose.
Code
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from matplotlib.path import Path
import math as mt
import random
def buildRectPath(edge, width):
theta = mt.atan((edge[1][1]-edge[0][1]) / (edge[1][0]-edge[0][0]+0.0000001)) # avoid ZeroDivisionError
x_left_top = edge[0][0] - mt.sin(theta) * width
y_left_top = edge[0][1] + mt.cos(theta) * width
x_left_bottom = edge[0][0]
y_left_bottom = edge[0][1]
x_right_top = edge[1][0] - mt.sin(theta) * width
y_right_top = edge[1][1] + mt.cos(theta) * width
x_right_bottom = edge[1][0]
y_right_bottom = edge[1][1]
verts = [(x_left_bottom, y_left_bottom), # left, bottom
(x_left_top, y_left_top), # left, top
(x_right_top, y_right_top), # right, top
(x_right_bottom, y_right_bottom), # right, bottom
(x_left_bottom, y_left_bottom),] # ignored
codes = [Path.MOVETO,
Path.LINETO,
Path.LINETO,
Path.LINETO,
Path.CLOSEPOLY,]
path = Path(verts, codes)
return path
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.axis('equal')
poly = [(1, 1), (2, 4), (4, 6), (6, 6), (8, 3), (1, 1)] # construct a random polygon
# expand each edge of the polygon (to different widths)
edges = [[(1, 1), (2, 4)], [(2, 4), (4, 6)], [(4, 6), (6, 6)], [(6, 6), (8, 3)], [(8, 3), (1, 1)]]
widths = [random.uniform(0.2, 0.5) for cnt in xrange(5)] # generate random widths for the 5 edges
for i, edge in enumerate(edges):
axes.plot([edge[0][0], edge[1][0]], [edge[0][1], edge[1][1]], color='b')
rectPath = buildRectPath(edge, widths[i])
rectPatch = patches.PathPatch(rectPath, facecolor='yellow', alpha=0.5)
axes.add_patch(rectPatch)
Output
Goal
I want to get a smooth contour of the shape. Basically, I am expecting two curves, one for inner loop and the other for the outer loop.
Note that
Since the widths of the lines are different, the contour that I am looking for is kind of like a fitting line that considers all the widths.
Currently there exist gaps between the rectangles. The contour should be a continuous curve that is gap-free.