pythonmatplotlibpolar-coordinatescartesian-coordinates

Generating a discrete polar surface map in cartesian coordinates


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:


Solution

  • One solution could be to put together the plot from wedge patches.

    enter image description here

    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()