Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
410 views
in Technique[技术] by (71.8m points)

python - How to use log scale on polar axis in matplotlib

I am trying to create a polar plot with a log scale on the radial axis but I keep getting an error. Some example code and the error are below. It seems to work fine in Cartesian coordinates, does anyone know what's happening??

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm

bazbins = np.linspace(0, 2*np.pi, 360)
fbins = np.logspace(np.log10(0.05), np.log10(0.5), 101)
theta, r = np.meshgrid(bazbins, fbins) 

# Set up plot window
fig, ax = plt.subplots(figsize=(12,9))#, subplot_kw=dict(projection='polar'))

# polar
ax.set_theta_zero_location('N')
ax.set_theta_direction(-1)
ax.set_rscale('log')

# carthesia
#ax.set_yscale('log')

# Plot data
#ax.pcolormesh(theta, r, r)
plt.gca().invert_yaxis()
ax.contourf(theta, r, r)
ax.set_ylim((0.0, 0.5))
plt.show()

Exception in Tkinter callback:

Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1413, in __call__
    return self.func(*args)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 236, in resize
    self.show()
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 239, in draw
    FigureCanvasAgg.draw(self)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_agg.py", line 421, in draw
    self.figure.draw(self.renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/figure.py", line 898, in draw
    func(*args)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 1997, in draw
    a.draw(renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/axis.py", line 1045, in draw
    tick.draw(renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/axis.py", line 239, in draw
    self.label1.draw(renderer)
  File "/usr/lib/pymodules/python2.7/matplotlib/artist.py", line 55, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/text.py", line 591, in draw
    ismath=ismath)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_agg.py", line 156, in draw_text
    return self.draw_mathtext(gc, x, y, s, prop, angle)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_agg.py", line 145, in draw_mathtext
    x = int(x) + ox
ValueError: cannot convert float NaN to integer
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Updated with matplotlib v3.3.4

  • Update def scatter_logpolar_mpl to use 'symlog', because using 'log' results in posx and posy should be finite values, and an empty plot for 'log-polar matplotlib'.
# updated function with symlog
def scatter_logpolar_mpl(ax, theta, r):
    ax.scatter(theta, r)
    ax.set_rlim(0)
    ax.set_rscale('symlog')
    ax.set_title('log-polar matplotlib')

# use other unchanged original functions

# setup the plot
r = np.arange(0, 3.0, 0.01) + 0.001

theta = 2 * np.pi * r

ax = plt.subplots(1, 3, subplot_kw=dict(polar=True), figsize=(12, 7))[1].flatten()
scatter_polar_mpl(ax[0], theta, r)
scatter_logpolar_mpl(ax[1], theta, r)
scatter_logpolar(ax[2], theta, r)

plt.tight_layout()
plt.show()

enter image description here

Original Answer

There are more problems with the current matplotlib and log-polar plots.

For example, try to add a small value to the radius in the matplotlib example for polar plots, and then use set_rlim(0) and set_rscale('log') to plot it (as has been suggested in the comments here). All values below 0.1 get some special treatment. This affects the ticks on the r axis (note the completely misplaced 10e-2 and 10e-3) as well as the plotted data:

Examples of polar and log-polar plots

The behavior seems to be undocumented. I ended up doing the log-transform manually (third plot in the series above). For others coming across this thread, here is my code:

import numpy as np
import matplotlib.pyplot as plt

def scatter_polar_mpl(ax, theta, r):
    ax.scatter(theta, r)
    ax.set_rlim(0)
    ax.set_title('polar matplotlib')
    
def scatter_logpolar_mpl(ax, theta, r):
    ax.scatter(theta, r)
    ax.set_rlim(0)
    ax.set_rscale('log')
    ax.set_title('log-polar matplotlib')
    
def scatter_logpolar(ax, theta, r_, bullseye=0.3, **kwargs):
    min10 = np.log10(np.min(r_))
    max10 = np.log10(np.max(r_))
    r = np.log10(r_) - min10 + bullseye
    ax.scatter(theta, r, **kwargs)
    l = np.arange(np.floor(min10), max10)
    ax.set_rticks(l - min10 + bullseye) 
    ax.set_yticklabels(["1e%d" % x for x in l])
    ax.set_rlim(0, max10 - min10 + bullseye)
    ax.set_title('log-polar manual')
    return ax
    
r = np.arange(0, 3.0, 0.01) + 0.001

theta = 2 * np.pi * r

ax = plt.subplots(1, 3, subplot_kw=dict(polar=True))[1].flatten()
scatter_polar_mpl(ax[0], theta, r)
scatter_logpolar_mpl(ax[1], theta, r)
scatter_logpolar(ax[2], theta, r)

plt.show()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...