3
votes

I have been looking for a way to reliably position the tick and axis labels in a plot in polar coordinates. Please take a look at the following example:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure(figsize=[10, 5])
ax0 = fig.add_axes([0.05, 0.05, 0.4, 0.9], projection="polar")
ax1 = fig.add_axes([0.55, 0.05, 0.4, 0.9], projection="polar")

r0 = np.linspace(10, 12, 10)
theta0 = np.linspace(0, 0.1, 10)

ax0.quiver(theta0, r0, -0.1, 0.1)
ax1.quiver(theta0 + np.pi, r0, -0.1, 0.1)

ax0.set_thetamin(-2)
ax0.set_thetamax(10)

ax1.set_thetamin(178)
ax1.set_thetamax(190)

for ax in [ax0, ax1]:

    # Labels
    ax.set_xlabel("r")
    ax.set_ylabel(r"$\theta$", labelpad=10)

    # R range
    ax.set_rorigin(0)
    ax.set_rmin(9)
    ax.set_rmax(13)

plt.show()

which results in this figure:

polar plot You can clearly see that

(a) the tick label position on the radial axis switches from bottom to top between the plots and the tick labels for theta switch from right to left.

(b) the axis label positions are fixed. I'd want the axis labels to also move with the tick labels. i.e. in the left plot, "theta" should be on the right, and in the right plot "r" should be on top.

How do I control the axis/tick labels in a way, so that they are positioned correctly? This even gets worse for e.g. a 90 degree shift, because then the theta axis is actually vertical and the tick labels are then totally off.

2
There is some consistency in what you observe here: Theta ticklabels are shown on the outside of the polar wedge - independent of the orientation. rticklabels are shown at the start of the theta axis (lowest angle). Both makes total sense to me. What I don't understand is the choice of the axis label position not coinciding with the ticklabels. This is to say, it's not obvious what "correct" means in this context. - ImportanceOfBeingErnest

2 Answers

2
votes

I think the most important bit is to become clear about how the usual notions of left, right, bottom, top translate into the polar axes in matplotlib.

enter image description here

The angular axis is the "x"-axis. The radial axis is the "y"-axis. The "bottom" is the outer ring. The "top" is the inner ring. "Left" is the radial axis at the start of the angular axis, "right" is the end of it.

This then allows to set the tick locations as usual, e.g.

ax.tick_params(labelleft=True, labelright=False,
               labeltop=False, labelbottom=True)

for the case shown above.

The x and y labels (set_xlabel / set_ylabel) are not translated. Here left, right, top, bottom refer to the cartesian definition, just as with normal linear axes. This means that for certain positions, they cannot be used to label the axis, because they are just too far away. An alternative is to create a text at the desired position.

A complete example code:

import numpy as np
import matplotlib.pyplot as plt

fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10,5), 
                               subplot_kw=dict(projection="polar"))

ax0.set(thetamin=180, thetamax=230)
ax1.set(thetamin=  0, thetamax= 50)

plt.setp([ax0, ax1], rorigin=0, rmin=5, rmax=10)

ax0.tick_params(labelleft=False, labelright=True,
                labeltop=True, labelbottom=False)

trans, _ , _ = ax1.get_xaxis_text1_transform(-10)
ax1.text(np.deg2rad(22.5), -0.18, "Theta Label", transform=trans, 
         rotation=22.5-90, ha="center", va="center")


plt.show()

enter image description here

1
votes

To answer question (b):

ax0.yaxis.set_label_position('right')
ax1.xaxis.set_label_position('top')

In addition, I modified the ax.set_ylabel(r"$\theta$", labelpad=15)

enter image description here