Как использовать логарифмическую шкалу на полярной оси в matplotlib
Я пытаюсь создать полярный график с логарифмической шкалой на радиальной оси, но получаю ошибку. Некоторые примеры кода и ошибки приведены ниже. Кажется, что он отлично работает в декартовых координатах, кто-нибудь знает, что происходит?
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()
Исключение в обратном вызове Tkinter:
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
4 ответа
Это похоже на ошибку в matplotlib. Вы не должны вызывать set_rlim
(или же set_ylim
) метод перед set_rscale
(или же set_yscale
). Кроме того, вы должны позвонить set_rlim
или же set_ylim
с 0 или 0.0 в качестве нижнего предела. Другие значения для нижнего предела также приведут к сбою. Проблема возникает и с другими бэкэндами (я подтвердил проблему с бэкэндами gtkagg и pdf).
Я подал отчет об ошибке по этой проблеме, который можно найти здесь. Если эта проблема касается вас, перейдите на страницу отчета об ошибке и оставьте комментарий, чтобы разработчики Matplotlib знали, что эта проблема важна для пользователей.
Есть больше проблем с текущими графиками matplotlib и log-polar.
Например, попробуйте добавить небольшое значение к радиусу в примере с matplotlib для полярных графиков, а затем используйте set_rlim(0)
а также set_rscale('log')
построить его (как было предложено в комментариях здесь). Все значения ниже 0,1 получают специальную обработку. Это влияет на клещей на r
ось (обратите внимание на полностью смещенные 10e-2 и 10e-3), а также нанесенные данные:
Поведение кажется недокументированным. В итоге я сделал log-transform вручную (третий график в серии выше). Для других, сталкивающихся с этой темой, вот мой код:
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()
Когда я вынимаю комментарий в строке, которая устанавливает окно графика, он запускается для меня.
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')
plt.gca().invert_yaxis()
ax.contourf(theta, r, r)
ax.set_ylim((0.0, 0.5))
plt.show()
Задавать rscale
после set_ylim()
, как тета ответил в комментариях выше.