Reorient Matplotlib polar plot - python

I would like to produce a polar scatterplot in matplotlib. The plot I have from using ax1 = plt.subplot(111, polar=True) looks fine, but I need to deviate from the usual polar graph orientation.
I need 0 degrees to point straight up (rotation).
I need 90 degrees to point right (mirror image).
(How) Can I do this?

You need ax.set_theta_zero_location and ax.set_theta_direction.
For details, see the doc
import matplotlib.pyplot as plt
import numpy as np
r = range(360)
angles = [i * np.pi / 180 for i in r]
f = plt.figure()
ax = plt.subplot(polar=True)
plt.polar(angles, r)
ax.set_xticks(angles[::10])
ax.set_theta_zero_location("N")
ax.set_theta_direction(-1)
plt.show()

Related

Rotate polar stereographic subplot

I am making a figure with subplots which are north polar stereographic projections. I also created a custom boundary shape to display subplot as a circle. However once reprojected, I want to be able to rotate the map, since my data is focusing on the US and thus I was hoping that each subplot would have the US facing "up," thus I would need to rotate it 270 degrees / -90 degrees.
Minimalistic code example pulled from cartopy example
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline # for notebook
map_projection = ccrs.NorthPolarStereo(central_longitude=0, )
data_projection = ccrs.PlateCarree()
theta = np.linspace(0, 2*np.pi, 100)
center, radius = [0.5, 0.5], 0.5 # by changing radius we can zoom in/out
verts = np.vstack([np.sin(theta), np.cos(theta)]).T
circle = mpl.path.Path(verts * radius + center)
plot_extent=[-179.9,180, 30, 90]
fig, ax1 = plt.subplots(1,1, figsize=(6,6), dpi=100, subplot_kw=dict(projection=map_projection))
ax1.set_boundary(circle, transform=ax1.transAxes)
ax1.coastlines(linewidths=1.0, color='grey')
ax1.add_feature(cfeature.BORDERS, linestyles='--', color='dimgrey', linewidths=0.8 )
ax1.set_extent(plot_extent, crs=ccrs.PlateCarree(),)
gl = ax1.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=1, color='gray', alpha=0.5, linestyle='--', zorder=10)
I haven't yet found any good examples or documentation for what I am trying to do, however I am new to using matplotlib/cartopy.
You need to set central_longitude=-90.
So:
map_projection = ccrs.NorthPolarStereo(central_longitude=-90)

Plot a 3-D surface from a table of coordinates in Python

I haven't found an answer to this yet: I have a grid defined in a text file with four columns: (lon,lat,depth,slip). Each row is a grid point.
I can generate a scatter plot of these points using the following simple code:
# Main imports:
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
# Read the grid:
points = np.loadtxt("grid.txt")
# Retrieve parameters from the grid:
lon = points[:,0]
lat = points[:,1]
depth = points[:,2]
slip = points[:,3]
# 3-D plot of the model:
fig = figure(1)
ax = fig.add_subplot(111, projection='3d')
p = ax.scatter(lon, lat, depth, c=slip, vmin=0, vmax=max(slip), s=30, edgecolor='none', marker='o')
fig.colorbar(p)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
jet()
grid()
show()
And I get the following figure:
What I want to do is to be able to interpolate those points to create a "continuous" surface grid and plot it in both 2-D and 3-D plots. Therefore, somehow I've to consider all (lon,lat,depth,slip) in the interpolation. I'd appreciate your suggestions. Thanks in advance!
I'm a bit late, but if your data grid is properly ordered, you could resolve your iusse using plot_surface reshaping your 1D data to 2D.
An example supposing you're using a 10x10 grid:
# Main imports:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# Set the fourth dimension`
color_dimension = slip.reshape(10,10)
# normalize the colours
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
# color map
m = plt.cm.ScalarMappable(norm=norm, cmap='hot')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
#reshape 1D data to 2D
g=ax.plot_surface(lat.reshape(10, 10), lon.reshape(10, 10), depth.reshape(10, 10), cmap='hot',rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)
cbar=fig.colorbar(g,aspect=50)
cbar.set_label('slip', rotation=270, fontsize=14)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
plt.show()

Polar chart issue in Python, angles not being taken into account

I am having some trouble with a polar chart I am working on. The figure I should get is an eight-shape (some friends of mine plotted the data in Origin and Excel and it does work), but it looks like the code is not properly written. By looking at the figure, I see that the code is not taking into account the angles I am writing (theta array), but I don't know why it happens. I've already tried some more codes and writing the angles in radians, but nothing seems to work.
import numpy as np
import matplotlib.pyplot as plt
from pylab import *
import matplotlib.pyplot as plt
from pylab import *
import numpy as np
r = np.array([11.7,12.1,10.1,6.6,3.1,1.5,2.3,5.2,
8.7,11.5,12,10.1,6.6,3.3,1.5,2.3,5.3,9.2,11.9])
theta =np.array([0,20,40,60,80,100,120,140,160,180,
200,220,240,260,280,300,320,340,360])
ax = plt.subplot(111, projection='polar')
ax.plot(theta,r)
ax.set_rmax(13)
ax.set_rticks([2,4,6,8,10,12]) # less radial ticks
ax.set_rlabel_position(-40) # get radial labels away from plotted line
ax.grid(True)
ax.set_title("A line plot on a polar axis", va='bottom')
plt.show()
I've also tried this:
r3 = np.array([11.7,12.1,10.1,6.6,3.1,1.5,2.3,5.2,
8.7,11.5,12,10.1,6.6,3.3,1.5,2.3,5.3,9.2,11.9])
theta3 =np.array([0,20,40,60,80,100,120,140,160,180,
200,220,240,260,280,300,320,340,360])
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
c = ax.scatter(theta3, r3)
Counter-intuitively, while the polar plot shows its theta axis in degrees, it actually expects the coordinates to be in radians:
import numpy as np
import matplotlib.pyplot as plt
r = np.array([11.7,12.1,10.1,6.6,3.1,1.5,2.3,5.2,
8.7,11.5,12,10.1,6.6,3.3,1.5,2.3,5.3,9.2,11.9])
theta =np.array([0,20,40,60,80,100,120,140,160,180,
200,220,240,260,280,300,320,340,360], dtype=float) # making sure it is float
# convert to radians
# theta *= np.pi/180.
theta = np.deg2rad(theta)
ax = plt.subplot(111, projection='polar')
ax.plot(theta,r)
ax.grid(True)
ax.set_title("A line plot on a polar axis", va='bottom')
plt.show()
I have not managed to find any place in the documentation, where this is explicitly stated (only examples where it is done correctly).
The weird pictures you got came from the fact that all values above 2pi are folded back into the range 0...2pi. So e.g. 20 % 2pi = 1.15, which is about 65 degrees when converted, which is where the second value is actually located in your plot.

Legend specifying 3d position in 3D axes matplotlib

I have a scatter 3d plot using matplotlib.
What I'm trying to do is to position the legend inside the plot. I have read the documentation and it seems that is only possible to select predefined positions or only specify x and y coordinates.
Is there a way to position the legend specifying the 3 coordinates?
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
#more code
ax.legend(loc=(0.5,0.5,0.5), frameon=0)
The last line is what I thought might work but obviously is not working.
This is what I've now:
I'm trying to position the legend inside the axes, sort of like:
I reached that position by trial and error using ax.legend(loc=(0.15,0.65),frameon=0) because the legend doesn't move as the axes are rotated. The issue is that I'll be doing several plots thus I'm trying to avoid the trial and error approach.
Thanks.
To place the legend in a 3D plot using data coordinates, one may first get the projected coordinates of a point in 3D space using
mpl_toolkits.mplot3d.proj3d.proj_transform(x,y,z, ax.get_proj())
and provide those to the bbox_to_anchor argument of the legend. Than changing the bbox_transform to the data coordinate system produces the desired plot.
The following places the lower left corner of the legend at position (70,1000,80) in data coordinates.
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D, proj3d
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = 25 * r * np.sin(theta)
y = 350* r * np.cos(theta)
ax.plot(x, y, 70*z, label='parametric curve')
ax.plot(x*.6, y*0.5, 70*z, label='parametric curve 2')
f = lambda x,y,z: proj3d.proj_transform(x,y,z, ax.get_proj())[:2]
ax.legend(loc="lower left", bbox_to_anchor=f(70,1000,80),
bbox_transform=ax.transData)
plt.show()

plot many circles based on x,y,r being vectors in python

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.

Categories

Resources