1

I want to align theta tick labels on a circle while also controlling start position and label order clockwise. Based on those two answers by ImportanceOfBeingErnest and Anmol Durgapal I was able to come up with this code, but that fails when I change the order and/or start with January north:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(6, 6))
ax1 = fig.add_subplot(projection="polar")

labels = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
angles = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]
theta_ticks = np.linspace(0.,330.,12)

plt.thetagrids(angles=angles, labels=labels)

for label, angle in zip(ax1.get_xticklabels(), theta_ticks):
    x, y = label.get_position()
    lab = ax1.text(x, y, label.get_text(), transform=label.get_transform(), ha=label.get_ha(), va=label.get_va())
    lab.set_rotation(angle-90)

ax1.set_xticklabels([])

plt.show()

resulting plot

When I now add

ax1.set_theta_offset(np.pi / 2)
ax1.set_theta_direction(-1)

i get this: misaligned labels

Any ideas on how I can achieve this result?

manually edited list example

This was achieved by editing the labels in reverse order and starting at April:

labels = ["April", "March", "February", "January", "December", "November", "October", "September", "August", "July", "June", "May"]

While that works it ruins the actual data I want to plot that relies on the theta_direction and offset.

  • what are toy actually trying to plot > the manually edited chart contains no data or plot line ? – D.L Sep 13 '22 at 15:46
  • I just constructed a minimal working example as the guide says. I'm just plotting bar sales data from a database and thought it would just distract since the problem is the labels and the polar projection. I can of course add some random data. – Henning Meier Sep 13 '22 at 16:28
  • an easy way to illustrate would be to just use `r = np.arange(0, 2, 0.01) # values for graph theta = 2 * np.pi * r # angles for graph ax = plt.subplot(111, projection='polar') ax.plot(theta, r)` That way the curve would move along with the rest of the labels as shown in the misaligned picture. – Henning Meier Sep 13 '22 at 17:03
  • the min working example is good, but if you could add datapoints to this to show what is not working it would help... – D.L Sep 13 '22 at 22:35

1 Answers1

0

While I could not find a solution to the specific question - that's how to use coordinate calculation to align the labels - I went a different way and separated data and labels into different axes. Being new to this I can't tell if that is a valid way of doing things, but it works.

Below is the minimal working example with these changes and toy data incorporated. Notice the end of the spiral lines up with January after being reversed and rotated independently of the labels. On the off-chance that anyone ever reads this, feel free to comment on anything that looks wrong.

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(6, 6))

# ax1 containing labels
ax1 = fig.add_subplot(label='labels', projection="polar")

labels = ["January","February","March","April","May","June","July","August","September","October","November","December"]

labels.reverse()
labels = labels[8:] + labels[:8]

angles = [0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330]
theta_ticks = np.linspace(0, 330, 12)

plt.thetagrids(
    angles=angles,
    labels=labels,
    fmt=None,
)  # theta grid with month labels

for label, angle in zip(ax1.get_xticklabels(), theta_ticks):
    x, y = label.get_position()
    lab = ax1.text(x, y, label.get_text(), transform=label.get_transform(), ha=label.get_ha(), va=label.get_va())
    lab.set_rotation(angle - 90)

ax1.set_xticklabels([])

# ax2 containing data rotated and reversed
ax2 = fig.add_subplot(label='data', projection="polar")
ax2.set_xticklabels([])

# toy data
r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * np.arange(0, 2, 0.01)

ax2.plot(theta, r)

ax2.set_axis_off()  # hide all decorations
ax2.set_theta_offset(np.pi / 2)  # start month labels north
ax2.set_theta_direction(-1)  # set month labels in clockwise order

plt.show()