I want to draw simple polygon that means there is no self-intersecting in the polygon using x & y locations. But what I got for the result is butterfly shape of polygon.
I know that if I change li_feasible_points to [[0,2],[2,2],[4,0],[2,0]] in order to draw simple polygon IN THIS TIME.
But WHAT I WANT is to draw simple polygon without self-intersecting by ANY list of corner points locations. Is there any way to solve this problem?
Here is my code and my result below.
from matplotlib import pyplot as plt
fig, ax = plt.subplots(figsize=(6, 6))
x_lim = 5
y_lim = 10
x = np.linspace(0, x_lim)
y = np.linspace(0, y_lim)
li_feasible_points = [[0.0, 2.0], [4.0, 0.0], [2.0, 0.0], [2.0, 2.0]]
line = plt.Polygon(li_feasible_points, closed=False, color='r', fill=True, edgecolor='r')
plt.gca().add_line(line)
plt.xlabel(li_var_names[0])
plt.ylabel(li_var_names[1])
plt.xlim(0, x_lim)
plt.ylim(0, y_lim)
plt.show()
I look forward to your help. Thank you.
Related
I am working on a program to add text labels above dots in a matplolib's 3d animation.
However when I use gca() to work on my label's axis (ax); I end up with two figures when calling plt.show().
two figures instead of one
---The program starts here---
import numpy as np
from PyAstronomy import pyasl
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import proj3d
import mpl_toolkits.mplot3d.axes3d as p3
satellites_values = [[1.0, 2.0, 0.50, 0.0, 30.0, 0.0], [1.0, 1.0, 0.20, 0.0, 90.0, 0.0], [10.0, 2.0, 0.39, 0.0, 180.0, 0.0]]
satellites_pos = []
red_dots_pos = []
fig = plt.figure()
ax = plt.figure().gca(projection='3d')
anim = []
def update(i, pos, red_dot, annotation):
red_dot.set_data([pos[i][1], pos[i][0]])
red_dot.set_3d_properties(pos[i][2])
x2, y2, _ = proj3d.proj_transform(pos[i][1], pos[i][0], pos[i][2], ax.get_proj())
annotation.set_position((x2,y2))
return red_dot, annotation
def create_system(satellites_list):
for satellite in satellites_list:
t = np.linspace(0, 4, 200)
orbit = pyasl.KeplerEllipse(a=satellite[0], per=satellite[1], e=satellite[2], Omega=satellite[3], i=satellite[4], w=satellite[5])
pos = orbit.xyzPos(t)
red_dot, = ax .plot(pos[::, 1], pos[::, 0], pos[::, 2], 'ro')
text = 'aaa'
annotation = ax.text2D(pos[::, 1],pos[::, 0], text)
anim.append(animation.FuncAnimation(fig, update, 200, fargs=(pos, red_dot, annotation), interval=100, blit=False))
ax.plot(pos[::, 1], pos[::, 0], pos[::, 2], 'k-')
create_system(satellites_values)
ax.plot([0], [0], [0], 'bo', markersize=20, label="Earth")
# Hide grid lines
ax.grid(False)
# Hide axes ticks
ax.set_xticks([])
ax.set_yticks([])
ax.set_zticks([])
plt.style.use('default')
plt.legend()
plt.show() ```
When I try:
ax = fig.gca(projection='3d')
or
ax = fig.add_subplot(111, projection='3d')
I get the following error:
TypeError: only size-1 arrays can be converted to Python scalars.
I want to have a unique figure because this program is part of a GUI that's supposed to show the dots with their label.
I was wondering if anyone here knew how to fix this.
I am trying to rotate the radial tick labels on the attached plot.
Why does matplotlib not rotate them when I have the 'rotation' command specified?
I would then like to shift the labels in the radial direction. Is there an equivalent of the 'pad' command with the polar charts?
import numpy as np
import matplotlib.pyplot as plt
import math
Graph_title = "Radar Plot"
def radarplot():
ax = plt.subplot(111, polar=True)
# INPUT DATA
n_directions = 12
angles = [n / float(n_directions) * 2 * math.pi for n in range(n_directions)]
data = [3.0, 3.0, 3.0, 3.0, 2.0, 2.5, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0]
# Add the last element of the list to the list. This is necessary or the line from 330 deg to 0 degree does not join up on the plot.
angles = np.append(angles, angles[:1])
data = np.append(data, data[:1])
ax.plot(angles, data, linewidth=2, linestyle='solid', color = 'red')
# Radial tick parameters
radial_ticks = [0.00, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00]
ax.set_rlabel_position(45)
ax.set_rorigin(0)
plt.yticks(radial_ticks, color='black', size=8)
ax.set_yticklabels(radial_ticks, rotation = 45, zorder = 500)
# X Tick parameters
plt.xticks(angles, color='black', size=10, zorder = 5)
ax.tick_params(axis='x', which='major', pad=3)
ax.set_theta_zero_location("N") # Sets the labels initial position to 0 degrees
ax.set_theta_direction("clockwise") # Set the labels to rotate clockwise
plt.savefig(Graph_title +".png", figsize = [6.4, 5], dpi=1000)
plt.show()
plt.close()
radarplot()
Recently I wanted to achieve the same thing as you and here is the solution that I came up with.
Suppress the automatic r tick labels using the command ax.set_yticklabels([])
For each radial tick define a tick list, a position list, and an alignment list.
Using the text command write the values in the tick list at the radial locations specified by the position list with alignment specified by the alignment list.
Essentially the r ticks can be moved along the radial direction by changing the values in the position list.
Make sure that the text command is specified with transform=ax.transData option.
import numpy as np
import matplotlib.pyplot as plt
import math
Graph_title = "Radar Plot"
def radarplot():
ax = plt.subplot(111, polar=True)
# INPUT DATA
n_directions = 12
angles = [n / float(n_directions) * 2 * math.pi for n in range(n_directions)]
data = [3.0, 3.0, 3.0, 3.0, 2.0, 2.5, 2.5, 2.5, 2.75, 2.75, 3.0, 3.0]
# Add the last element of the list to the list. This is necessary or the line from 330 deg to 0 degree does not join up on the plot.
angles = np.append(angles, angles[:1])
data = np.append(data, data[:1])
ax.plot(angles, data, linewidth=2, linestyle='solid', color = 'red')
r_ticks = [0.00, 0.50, 1.00, 1.50, 2.00, 2.50, 3.00] #tick list
r_ticks_pos = [0.20, 0.65, 1.15, 1.65, 2.15, 2.65, 3.25] #radial position list (CHANGE THESE VALUES TO MOVE EACH TICK RADIALLY INDIVIDUALLY)
r_ticks_h_align = ['center','center','center','center','center','center','center'] #horizontal alignment list
r_ticks_v_align = ['center','center','center','center','center','center','center'] #vertical alignment list
r_label_angle = 45 #theta angle
# Radial tick parameters
ax.set_rlabel_position(r_label_angle)
ax.set_rorigin(0)
ax.set_yticklabels([])
ax.set_rticks(r_ticks)
ax.set_rlabel_position(r_label_angle)
#write the ticks using the text command
for rtick, rtick_pos, rtick_ha, rtick_va in zip(r_ticks, r_ticks_pos, r_ticks_h_align, r_ticks_v_align):
plt.text(np.radians(r_label_angle), rtick_pos, r'$'+str(rtick)+'$', ha=rtick_ha, va=rtick_va, transform=ax.transData, rotation=-45, fontsize=8)
# X Tick parameters
plt.xticks(angles, color='black', size=10, zorder = 5)
ax.tick_params(axis='x', which='major', pad=3)
ax.set_theta_zero_location("N") # Sets the labels initial position to 0 degrees
ax.set_theta_direction("clockwise") # Set the labels to rotate clockwise
plt.savefig(Graph_title +".png", figsize = [6.4, 5], dpi=1000)
plt.show()
plt.close()
radarplot()
And the result:
I meet the same problem, and I only solved the rotation problem. axis='x' failed to control the rotation, only axis='both' can work.
ax.tick_params(
axis='both',
labelrotation=-45.,
)
I am trying to solve the pad problem.
I am using Python3.6.5 from an Anaconda install.
I have 16 data files containing two columns of data. I am trying to make a plot that shows all the data in one 4x4 plot. I have managed to get all the plots plotted on a large 4x4 plot, but can't adjust the X and Y ticks. The X values range from 0 to 2000 and the Y values range from 0 to 4.5.
This is my current script:
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import math
ph_values = [1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5]
all_xs = []
all_ys = []
for ph in ph_values:
xs = []
ys = []
with open('rmsd_ph' + str(ph) + '.dat', "r") as f:
for line in f:
if line[0] != "#":
x,y = line.split()
xs.append(float(x))
ys.append(float(y))
all_xs.append(xs)
all_ys.append(ys)
fig, axes = plt.subplots(nrows=math.ceil(len(ph_values)/4), ncols=4, figsize=(6,6))
axes = axes.flatten()
for index,ph in enumerate(ph_values):
axes[index].plot(np.asarray(all_xs[index]),np.asarray(all_ys[index]))
plt.xticks(np.arange(0, 2000, step=500))
plt.tight_layout()
plt.savefig('test.pdf')
plt.show()
Currently the script outputs something that looks like this.
As you can see the last plot has the X-axis adjusted. I have not tried to adjust the Y-axis yet because I have not not been successful with the y axis.
Overall, I would like 4 ticks on both the y and x axis.
This is what I found that answered the problem I was having.
fig, axes = plt.subplots(nrows=math.ceil(len(ph_values)/4), ncols=4, figsize=(9,9))
axes = axes.flatten()
for index,ph in enumerate(ph_values):
axes[index].scatter(np.asarray(all_xs[index]),np.asarray(all_ys[index]), s=1)
plt.sca(axes[index]) <------------------ Fixed Problem
plt.xticks([0, 500, 1000, 1500, 2000]) <- Fixed Problem
plt.yticks([0, 1, 2, 3, 4, 5]) <---------- Fixed Problem
plt.title('pH:' + str(ph))
if (index % 4 == 0):
plt.ylabel('RMSD [$\\rm{\\AA}$]')
if (index >= 12):
plt.xlabel('Steps')
plt.tight_layout()
plt.savefig(output)
plt.show()
Here is an image of the result.
If I understand right that you'd like to have all x-axes comparable the same and so the y-axes, too, I'd recommend to try shared axes:
fig, axes = plt.subplots(4, 4, sharex=True, sharey=True, figsize=(6,6))
I have 4 dots which are represented with these coordinates:
X = [0.1, 0.5, 0.9, 0.18]
Y = [0.7, 0.5, 0.7, 0.3]
Z = [4.2, 3.3, 4.2, 2.5]
and I have to get the best linear function (plane) which approximate these 4 dots.
I'm aware of numpy.polyfit, but polyfitworks only with x and y (2D),
What can I do?
while not completely general, if the the data points can be reasonably represented as a surface relative to a coordinate plane, say z = ax + by + c then np.linalg.lstsq can be used
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
X = np.array([0.1, 0.5, 0.9, 0.18])
Y = np.array([0.7, 0.5, 0.7, 0.3])
Z = np.array([4.2, 3.3, 4.2, 2.5])
# least squares fit
A = np.vstack([X, Y, np.ones(len(X))]).T
a,b,c= np.linalg.lstsq(A, Z)[0]
# plots
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# plot data as big red crosses
ax.scatter(X, Y, Z, color='r', marker='+', linewidth=10)
# plot plane fit as grid of green dots
xs = np.linspace(min(X), max(X), 10)
ys = np.linspace(min(Y), max(Y), 10)
xv, yv = np.meshgrid(xs, ys)
zv = a*xv + b*yv + c
ax.scatter(xv, yv, zv, color = 'g')
# ax.plot_wireframe(xv, yv, zv, color = 'g') # alternative fit plane plot
plt.show()
plotting the data 1st, you could select a different coordinate pair for the "independent variable" plane to avoid ill conditioned result if necessary, if the data points appeared to lie in a plane containing the z axis, then use xz or yz
and of course you could have degenerate points on a line or the vertices of a regular tetrahedron
for a better "geometric fit" the 1st fitted plane could be used as the base for a 2nd least square fit of the data rotated into that coordinate system (if the data is "reasonably" plane like)
(I've asked the same in MATLAB before)
I'd like to overlay for example a seismic-cmapped contourf-plot (or pcolor) with a grayscale contour-plot, but when I add the latter it also changes the previous colormap. How can this be fixed?
This answer is taken almost entirely from the contour demo example:
import numpy as np
import matplotlib.cm as cm
import matplotlib.mlab as mlab # for setting up the data
import matplotlib.pyplot as plt
# set up example data:
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
levels = 10
# plot the filled contour
# using a colormap (jet)
CF = plt.contourf(Z, levels,
extent=(-3,3,-2,2),cmap=cm.jet)
# plot the contour lines
# using gray scale
CL = plt.contour(Z, levels,
linewidths=2,
extent=(-3,3,-2,2),cmap=cm.gray)
# plot color bars for both contours (filled and lines)
CB = plt.colorbar(CL, extend='both')
CBI = plt.colorbar(CF, orientation='horizontal')
# Plotting the second colorbar makes
# the original colorbar look a bit out of place,
# so let's improve its position.
l,b,w,h = plt.gca().get_position().bounds
ll,bb,ww,hh = CB.ax.get_position().bounds
CB.ax.set_position([ll, b, ww, h])
plt.show()
And you'll end up with this plot: