I would like to generate a surface plot with discrete arc-shaped cells on a 2D cartesian plane. I am able to get decent results by plotting a 3D surface plot (using plot_surface
) and viewing it from the top, but matplotlib can be a bit finicky with 3D, so I'd prefer to do it in 2D. I can also get similar results using pcolormesh
on a polar plot, but again, I want a 2D cartesian plane. How can I do this in matplotlib?
MRE:
import numpy as np
import matplotlib.pyplot as plt
r = np.linspace(2, 5, 25)
theta = np.linspace(0, np.pi, 25)
R, Theta = np.meshgrid(r, theta)
X = R*np.cos(Theta)
Y = r*np.sin(Theta)
U = R*np.cos(Theta)*np.exp(R*Theta/500)
fig, ax = plt.subplots(figsize=(8,6), subplot_kw={"projection":"3d"})
surf = ax.plot_surface(X, Y, U, cmap="viridis", rstride=1, cstride=1)
ax.view_init(elev=90, azim=-90)
ax.set_proj_type("ortho")
ax.zaxis.line.set_lw(0.)
ax.set_zticks([])
ax.set_aspect("equalxy")
fig.colorbar(surf, shrink=0.5, aspect=5)
fig.tight_layout()
fig, ax = plt.subplots(figsize=(8,6), subplot_kw={"projection":"polar"})
ax.pcolor(Theta, R, U, shading="nearest")
ax.set_xlim(0, np.pi)
ax.grid(False)
fig.tight_layout()
3D plot version:
2D polar plot version:
One solution could be to put together the plot from wedge patches.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Wedge
from matplotlib.collections import PatchCollection
r = np.linspace(2, 5, 25)
theta = np.linspace(0, np.pi, 25)
r_mid = 0.5 * (r[:-1] + r[1:])
theta_mid = 0.5 * (theta[:-1] + theta[1:])
R, Theta = np.meshgrid(r_mid, theta_mid)
U = R * np.cos(Theta) * np.exp(R * Theta / 500)
patches = []
color = []
for i in range(len(theta) - 1):
for j in range(len(r) - 1):
t0, t1 = np.degrees(theta[i]), np.degrees(theta[i+1]) #angle bounds in degrees
r0, r1 = r[j], r[j+1] #radial bounds
wedge = Wedge(center=(0, 0), r=r1, theta1=t0, theta2=t1, width=r1 - r0)
patches.append(wedge)
color.append(U[i, j]) #coloring
fig, ax = plt.subplots(figsize=(8, 6))
collection = PatchCollection(patches, array=np.array(color), cmap='viridis', edgecolor=None)
ax.add_collection(collection)
ax.set_xlim(-5.5, 5.5)
ax.set_ylim(-0.5, 5.5)
ax.set_aspect('equal')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_color('black')
ax.spines['left'].set_color('black')
fig.colorbar(collection, ax=ax, shrink=0.5)
plt.tight_layout()
plt.show()