Search code examples
pythonmatplotlibcontour

Create Polar Contour Plot


I am trying to recreate the contour plot shown below in Matplotlib, using the following code to generate the data:

theta = np.arange(math.radians(0), math.radians(361),0.01).tolist() # initialise theta values
g4 = []
for i in theta:
    v = ((2**(1-1)) * (1 + (1*math.cos(i)))**1) # equation to generate the data
g4.append(v)

fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.scatter(theta, g4, c=g4, cmap='viridis')

enter image description here

So far, I have been able to generate a scatter plot using this data which looks as follows:

enter image description here

However I am completely unsure of how to convert my data into the correct form to produce the required scatter plot, I have tried:

ax.contourf(theta, g4, g4)

But I get TypeError: Input z must be 2D, not 1D


Solution

  • Based on the answer here, you could do:

    azimuths = np.radians(np.linspace(0, 360, 50))
    zeniths = np.linspace(0, 4, 50)
    
    r, theta = np.meshgrid(zeniths, azimuths)
    
    f = 1 + np.cos(theta)  # your function is essentially this
    
    fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
    
    ax.contourf(theta, r, f)
    

    which produces:

    enter image description here

    This obviously doesn't look like the example plot that you show, but that's because your function is only a function of theta and not of r. So, it is therefore constant in the radial direction for any value of theta.

    To get something similar to the example plot, you could add the r variable in to the function, e.g.:

    azimuths = np.radians(np.linspace(0, 360, 250))
    zeniths = np.linspace(0, 4, 250)
    
    r, theta = np.meshgrid(zeniths, azimuths)
    
    # function that also depends on r
    f = 1 + np.cos(theta) - (0.35 * r)**2
    
    fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
    
    f[f <= 0] = np.inf  # mask out values that are negative
    
    ax.grid()
    ax.pcolormesh(theta, r, f, cmap="viridis_r")  # plot function
    ax.grid(True)
    ax.contour(theta, r, f, levels=10, colors="k", linewidths=0.25)  # add contours
    ax.set_rticks([0, 1, 2, 3, 4]);  # set radial tick values
    

    enter image description here