Search code examples
pythonmatplotlibplotaxis-labelspolar-coordinates

Matplotlib polar plotting: displaying polar tickmarks in degrees, with decimal format


I am attempting to label the tickmarks on a polar sector plot in Matplotlib in degrees following a specified format (i.e., a float with two decimal places), but doing both of these is not clearly supported.

I am able to label the tickmarks as degrees or with specified decimal places, but not both. Note that Matplotlib defaults to tickmarks in degrees:

But after I apply a format to the tickmarks using ax.xaxis.set_major_formatter(), radians are displayed instead: enter image description here

How can I enforce the degree format while also specifying the decimal format?

Note: converting the tickmarks to degrees (e.g., numpy.rad2deg) does not work, since ax.set_xticks() interprets the argument as radians only (and yet, Matplotlib displays them as degrees by default...)

Sample code:

import numpy as np
import matplotlib.pyplot as plt

from matplotlib.ticker import FormatStrFormatter

minTheta = 0.42; maxTheta = 0.55

fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')

#create four tick labels (in radians) dynamically based on the theta range
ticks = np.linspace(minTheta, maxTheta, 4)

ax.set_xticks(ticks)

#disable or enable the following line to change the tick display format*************
ax.xaxis.set_major_formatter(FormatStrFormatter('%.2f'))

#Adjust the sector window: you must call these AFTER setting the ticks, since setting the ticks
#actually adjusts the theta range window. This must be in degrees.
ax.set_thetamin(np.rad2deg(minTheta))
ax.set_thetamax(np.rad2deg(maxTheta))

Solution

  • The internal units of the polar plot are radians. The position of the ticks is hence given in radians and those are the numbers you need to format. You can do so using a FuncFormatter.

    rad2fmt = lambda x,pos : f"{np.rad2deg(x):.2f}°"
    ax.xaxis.set_major_formatter(FuncFormatter(rad2fmt))
    

    Complete example would look like:

    import numpy as np
    import matplotlib.pyplot as plt
    
    from matplotlib.ticker import FuncFormatter
    
    minTheta = 0.42; maxTheta = 0.55
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='polar')
    
    #create four tick labels (in radians) dynamically based on the theta range
    ticks = np.linspace(minTheta, maxTheta, 4)
    ax.set_xticks(ticks)
    
    #disable or enable the following line to change the tick display format*
    rad2fmt = lambda x,pos : f"{np.rad2deg(x):.2f}°"
    ax.xaxis.set_major_formatter(FuncFormatter(rad2fmt))
    
    #Adjust the sector window: you must call these AFTER setting the ticks, since setting the ticks
    #actually adjusts the theta range window. And it must be in degrees.
    ax.set_thetamin(np.rad2deg(minTheta))
    ax.set_thetamax(np.rad2deg(maxTheta))
    
    plt.show()
    

    enter image description here