1

I want to draw some circular axes to plot the artwork for an old-fashioned circular slide rule. In almost every example, polar plots have an angular axis of degrees or radians. I found one example of changing the labels to be like a clock (1 - 12), but I couldn’t see how to extend that technique to logarithmic scales.

I can draw the desired axis in a linear manner, as I see examples of making a logarithmic radial axis. But I can’t find a way to apply log scales to the angular theta axis.

A somewhat related issue, how can you use matplotlib to draw a single axis (e.g., no data, axis only)? This could be helpful for making nomographs, for example. In my use case, if I can’t plot the circular log scale directly, I could perhaps post-process a linear log scale into a circle — maybe.

Here is an old circular slide rule as an example. I’d like to make scales such as C or D (one complete log cycle in 360 degrees), A (two cycles) and K (three cycles).

3
  • Could you maybe link to the example you mentioned? Is it this one? stackoverflow.com/questions/36919275/… Commented Sep 6, 2021 at 20:57
  • If you're following the question I mentioned above, the linearity stems from np.linspace(0, 2pi, 24) in ax.set_xticks(). If you want some kind of logarithmic scaling, you should opt for some logarithmic mapping that maps your tick points between 0 and 2pi instead of a np.linspace Commented Sep 6, 2021 at 21:07
  • This is the example I saw. But similar concept. Commented Sep 6, 2021 at 22:49

2 Answers 2

3

Try this

import numpy as np
import matplotlib.pyplot as plt     

ax = plt.subplot(111, polar=True)


lim_min = 1             # ln(1) = 0
lim_max = np.e**(2*np.pi)  # ln(e**(2*pi)) = 2*pi (np.log = ln)
N_LABLES = 24
XTICKS = [np.log(x) for x in np.linspace(lim_min, lim_max, N_LABLES, endpoint=False)]

# Set the circumference labels
ax.set_xticks(XTICKS)
ax.set_xticklabels(range(N_LABLES))

# Make the labels go clockwise
ax.set_theta_direction(-1)

# Place 0 at the top
ax.set_theta_offset(np.pi/2.0)       

plt.show()

You can play with the exact scaling from 0 to 2pi to get the plot the way you want it. Figure produced: enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

This seems to be the way to go, for my application. I kept wanting to use the LogFormatter, like I would for a linear log axis, but finally I decided it wasn't suitable. There are only two levels of tick marks native to matplotlib, but to draw slide rule scales you need 3 or 4 levels. This approach lets me do that, albeit a little tedious. I will post my modification to your code below, which draws one cycle of a log scale. Thanks @ljbkusters
2

Based on @ljbkusters answer, I crafted a single-cycle, circular log-base-10 scale. This will serve as a basis for more detailed plots for the final slide rule artwork.

import numpy as np
import matplotlib.pyplot as plt     

ax = plt.subplot(111, polar=True)

# Make the labels go clockwise
ax.set_theta_direction(-1)
# Place 0 at the top
ax.set_theta_offset(np.pi/2.0)       

# Polar plots don't have tick marks, 
# cannot draw outside the max radius set by ylim
# Remove the frame, and y-axis,
# * draw our own axis circle
# * draw our own tick marks (below)
ax.set_ylim(0,100)
ax.grid(False)
ax.set_frame_on(False)
ax.axes.get_yaxis().set_visible(False)
angles = np.linspace(0.0, 2.0*np.pi, 100)
ax.plot( angles, 100*[95], color='black', lw=1.2 )

# Major
lim_min = 1 
lim_max = 10 
N_LABLES = 10
XTICKS = [2.0 * np.pi * np.log10(x) for x in np.linspace(lim_min, lim_max, N_LABLES-1, endpoint=False)]
ax.set_xticks(XTICKS)
# Set the circumference labels
ax.set_xticklabels(range(1, N_LABLES))
# Draw major tick marks
tick = [93,100]
for t in XTICKS:
    ax.plot([t,t], tick, lw=1.0, color='black')

# Minor
lim_min = 1 
lim_max = 10 
N_LABLES = 100
XTICKS = [2.0 * np.pi * np.log10(x) for x in np.linspace(lim_min, lim_max, N_LABLES-1, endpoint=False)]
ax.set_xticks(XTICKS)
# Draw minor tick marks
tick = [95,98]
for t in XTICKS:
    ax.plot([t,t], tick, lw=0.5, color='blue')

plt.show()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.