I would like to plot concentric circles at a given set of distances away from a source. The first thing I tried to do was draw an arc on polar plot, as this seemed like a logical substep:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)
ax.plot([1.0,1.5], [5,5], color='r', linestyle='-')
plt.show()
The first problem I'm having is that this draws a straight line rather than an arc:
So the subquestion might be how do I draw an arc, in this case a 360 degree arc, at a given radius on a polar plot?. On the other hand, there might be a better solution altogether, perhaps one that doesn't involve a polar plot. Ultimately, as per the title, my objective is to draw concentric circles at a set of radii around a centre source.
easy, use it to make shooting targets all the time.:
ax.plot(np.linspace(0, 2*np.pi, 100), np.ones(100)*5, color='r', linestyle='-')
Just think of how you define a circle in a polar axis? Need two things, angle and radius. Those are np.linspace(0, 2*np.pi, 100) and np.ones(100)*5 here. If you just need a arc, change the first argument to something less than 0 to 2pi. And change the 2nd argument accordingly.
There are other ways to do this. plot() creates .lines.Line2D object objects, if you want .collections.PathCollection object instead of Line2D:
ax.scatter(1, 0, s=100000, facecolors='none')
Or you want to make patches:
ax.bar(0, 5, 2*np.pi, bottom=0.0, facecolor='None') #need to modified the edge lines or won't look right
Related
I have a triangular surface mesh, generated via marching cubes. I want to color the surface elements based on an arbitrary variable in my plot. I am currently using plot_trisurf, but as I read the documentation, it looks like the color is always based on the Z component, or else a constant? Can I not specify a color per element? Or is there a better plot routine to use? For example, something along the lines of the code below is what I am after, where the color is based on the 'value' output from the marching cubes. Thanks!
import numpy as np
import matplotlib.pyplot as plt
from skimage import measure
from skimage.draw import ellipsoid
from matplotlib import cm
# Generate a level set about zero of two identical ellipsoids in 3D
ellip_base = ellipsoid(6, 10, 16, levelset=True)
# Use marching cubes to obtain the surface mesh of these ellipsoids
verts, faces, normals, values = measure.marching_cubes_lewiner(ellip_double, 0)
fig = plt.figure(figsize=(20, 10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:,1], verts[:, 2], triangles=faces, cmap=cm.rainbow, color=values)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
ax.set_xlim(0, 24)
ax.set_ylim(0, 20)
ax.set_zlim(0, 32)
plt.tight_layout()
plt.show()
As noted by JohanC, in this question they reset the face colors after the fact. This works for me, as I already have an array of colors defined.
# set the face colors of the Poly3DCollection
p3dc.set_fc(colors)
I am trying to add an image behind each subplot of my scatter plot figure. I want my image to take up all the subplot space. But I do not want to map my scatter points onto the image: That is, I want the axes of my scatter points to be independent to that of the image.
When I simply use imread() and implot() while making a subplot to insert the image, like so:
im = plt.imread("/Users/mac/Desktop/image.jpeg")
two = plt.subplot(222)
implot = plt.imshow(im)
plt.title('4-8 Hz')
plt.scatter(X,Y, s=100, marker ='o', c=AveragedHursts4to8, cmap = cm.plasma)
plt.colorbar()
two.axis('off')
I get the right-most image down below, where, clearly, the image axes and scatter points axes are shared.
I tried to use the twiny() function to make a new set of axes for the image, with the image set as the first axes and the second axes set to the scatter points, like so:
onetwin = plt.subplot(221)
plt.title('1-4 Hz')
implot = plt.imshow(im, zorder=1)
onetwin.axis('off')
one = onetwin.twiny()
plt.scatter(X,Y, s=100, marker ='o', c=AveragedHursts1to4, cmap = cm.plasma, zorder = 2)
plt.colorbar()
one.axis('off')
There I get the leftmost image, where the scatter points are squished on the y axis and the image, for some reason, has been shrunk.
And when I switch the ordering of the creation of the axes for twiny, the image takes up the whole subplot and the scatter points do not show at all.
Suggestions?
My suggestion would be to leave the points' positions untouched and scale the background image accordingly. One can use the extent keyword to imshow for that purpose.
In the example below I plot some random points on four different scales. Each time the image is scaled to the scatterplot's dimensions using the extent keyword.
import matplotlib.pyplot as plt
import numpy as np
x = np.random.rand(8*8).reshape((8,8))
image = plt.imread("https://upload.wikimedia.org/wikipedia/en/2/27/EU_flag_square.PNG")
fig, ax = plt.subplots(ncols=4, figsize=(11,3.8))
for i in range(len(ax)):
ax[i].scatter(x[2*i,:]*10**(i-1), x[2*i+1,:]*10**(i-1), c="#ffcc00", marker="*", s=280, edgecolors='none')
xlim = ax[i].get_xlim()
ylim = ax[i].get_ylim()
mini = min(xlim[0],ylim[0])
maxi = max(xlim[1],ylim[1])
ax[i].imshow(image, extent=[mini, maxi, mini, maxi])
plt.tight_layout()
plt.show()
The simplest, fastest solution I came up with is to solve for x and y in:
largest_x_coodinate_value(x) = x_dimension of image_in_pixels
largest_y_coordinate_value(y) = y_dimension_of_image_in_pixels
And then do vectorized multiplication over the numpy arrays containing the X and Y coordinates with those calculated x,y values, effectively scaling the coordinates to the size of the image.
I am trying to plot a circle on a grid. The code that I have written is as follows:
import pyplot as plt
from pyplot import Figure, subplot
fig=plt.figure(1)
plt.axis([0,400,0,400])
ax=fig.add_subplot(1,1,1)
circ=plt.Circle((200,200), radius=10, color='g', fill=False)
ax.add_patch(circ)
plt.show()
Now, I want the center of the circle to be the center of the graph, that is, (200,200) in this example. In case of other cases I want it to automatically choose the centre depending on the size that us set. Can this be in some way?
To make it clearer I want to get the x-axis and the y-axis range so as to find the mid point of the grid. How do I proceed?
Your x-axis and y-axis ranges are in your code right here:
plt.axis([0,400,0,400])
So all you would need is leverage on this a bit like so:
x_min = 0
x_max = 400
y_min = 0
y_max = 400
circle_x = (x_max-x_min)/2.
circle_y = (y_max-y_min)/2.
circ=plt.Circle((circle_x,circle_y), radius=10, color='g', fill=False)
If you want to catch x_min etc. from the command prompt then read out sys.argv.
What you want may be ax.transAxes, here's the tutorial for coordinates transformation.
ax.transAxes means the coordinate system of the Axes; (0,0) is bottom left of the axes, and (1,1) is top right of the axes.
fig=plt.figure(1)
plt.axis([0,400,0,400])
ax=fig.add_subplot(1,1,1)
circ=plt.Circle((0.5,0.5), radius=0.2, color='g', fill=False,transform=ax.transAxes)
ax.add_patch(circ)
plt.show()
Note that the radius is also transformed into Axes coordinate. If you specify a radius larger than sqrt(2)/2 (about 0.7) you will see nothing in the plot.
If you want to plot a set of circles, it would be much simpler if you use the function circles here. For this problem,
fig=plt.figure(1)
plt.axis([0,400,0,400])
ax=fig.add_subplot(1,1,1)
circles(0.5, 0.5, 0.2, c='g', ax=ax, facecolor='none', transform=ax.transAxes)
plt.show()
A bit more, if you want see a real circle (instead of an ellipse) in your figure, you should use
ax=fig.add_subplot(1,1,1, aspect='equal')
or something like that.
x,y are positions of the circles and r is the radius - all vectors.I want to plot them all at once. Something like:
import matplotlib.pyplot as plt
from matplotlib.patches Circle
#define x,y,r vectors
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
plt.Circle((x,y),r,color='r')
plt.show()
Thanks.
plt.scatter allows you to define a radius of the points plotted.
From the doc
matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o')
[...]
s:
size in points^2. It is a scalar or an array of the same length as x and y.
Playing with facecolor and edgecolor you should be able to get what you want
You can find an example in How to set_gid() for each bubble in matplot scatter chart?
I am not informed about the Circles patch, but here is how you can do it with the standard plot command:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([0.2,0.4])
y = np.array([0.2,1.2])
r = np.array([0.5,0.3])
phi = np.linspace(0.0,2*np.pi,100)
na=np.newaxis
# the first axis of these arrays varies the angle,
# the second varies the circles
x_line = x[na,:]+r[na,:]*np.sin(phi[:,na])
y_line = y[na,:]+r[na,:]*np.cos(phi[:,na])
plt.plot(x_line,y_line,'-')
plt.show()
The basic idea is to give the plt.plot(...) command two 2D arrays. In that case they are interpreted as a list of plots. Espacially for many plots (=many circles) this is much faster, than plotting circle by circle.
I have drawn a polar contour plot in Matplotlib as described in this question. This basically works by converting the polar co-ordinates to cartesian co-ordinates and then plotting in the cartesian co-ordinate system.
However, I want to be able to have a set of polar co-ordinate system axes overlain on the plot - that is, radial axes (sticking out from the centre) at 0, 90, 180 and 270 degrees, with ticks on them showing the radius at various points.
I have absolutely no idea how to go about doing this, and can't seem to find anything in documentation. Any suggestions?
fig = plt.figure(0)
rect = [0.1,0.1,0.8,0.8]
theta = np.linspace(0,2*np.pi,12)
line = np.random.rand(5)
r = np.linspace(1,1,12)
ax_carthesian = fig.add_axes(rect, ylim=(6.5,10.5), xlim=(-2,2), aspect='equal')
ax_carthesian.set_xlabel('X [kpc]')
ax_carthesian.set_ylabel('Y [kpc]')
# the polar axis:
ax_polar = fig.add_axes(rect, polar=True, frameon=False, xticks=([]), yticks=([]))
ax_polar.set_xticklabels(['','l=135','','l=225','','l=315','','l=45'])
ax_polar.set_yticklabels([]) #no radial ticks
# plotting on the carthesian axis
im = ax_carthesian.scatter(x_stuff, y_stuff, cmap='magma')
ax_polar.grid(True)
bothaxes = [ax_carthesian, ax_polar]
cbar = plt.colorbar(im, ax = bothaxes)
cbar.ax.set_ylabel('Log I_CO [K]')