Создание цветовой шкалы для графика, созданного с помощью plt.fill - PullRequest
8 голосов
/ 18 января 2012

Я новичок в Python (ранее был пользователем IDL), поэтому я надеюсь, что задаю этот вопрос понятным образом. Я пытался создать полярный график с количеством ячеек x, где данные в ячейке усредняются и получают цвет, связанный с этим значением. Кажется, это работает нормально при использовании команды plt.fill, где я могу определить корзину, а затем цвет заливки. Проблема возникает, когда я пытаюсь сделать цветную полосу, чтобы идти с ней. Я продолжаю получать сообщения об ошибках AttributeError: у объекта 'Figure' нет атрибута 'autoscale_None'

Любой совет будет полезен, спасибо.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.pyplot import figure, show, rc, grid
import pylab

r = np.arange(50)/5.
rstep = r[1] - r[0]
theta = np.arange(50)/50.*2.*np.pi
tstep = theta[1] - theta[0]
colorv = np.arange(50)/50.

# force square figure and square axes looks better for polar, IMO
width, height = mpl.rcParams['figure.figsize']
size = min(width, height)
# make a square figure
fig = figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, .8, .8])#, polar=True)

my_cmap = cm.jet
for j in range(len(r)):
    rbox = np.array([r[j], r[j], r[j]+ rstep, r[j] + rstep])
    for i in range(len(theta)):
        thetabox = np.array([theta[i], theta[i] + tstep, theta[i] + tstep, theta[i]])
        x = rbox*np.cos(thetabox)
        y = rbox*np.sin(thetabox)
        plt.fill(x,y, facecolor = my_cmap(colorv[j]))



# Add colorbar, make sure to specify tick locations to match desired ticklabels
cbar = fig.colorbar(fig, ticks=[np.min(colorv), np.max(colorv)])
cb = plt.colorbar()
plt.show()

* вот несколько лучший пример моих реальных данных, везде пропущены дыры, поэтому в этом примере я только что сделал большую четверть круга. Когда я попытался создать сетку, кажется, что код пытается интерполировать эти области.

r = np.arange(50)/50.*7. + 3.
rstep = r[1] - r[0]
theta = np.arange(50)/50.*1.5*np.pi - np.pi
tstep = theta[1] - theta[0]
colorv = np.sin(r/10.*np.pi)

# force square figure and square axes looks better for polar, IMO
width, height = mpl.rcParams['figure.figsize']
size = min(width, height)
# make a square figure
fig = figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, .8, .8])#, polar=True)

my_cmap = cm.jet

for j in range(len(r)):
    rbox = np.array([r[j], r[j], r[j]+ rstep, r[j] + rstep])
    for i in range(len(theta)):
        thetabox = np.array([theta[i], theta[i] + tstep, theta[i] + tstep, theta[i]])
        x = rbox*np.cos(thetabox)
        y = rbox*np.sin(thetabox)
        plt.fill(x,y, facecolor = my_cmap(colorv[j]))


# Add colorbar, make sure to specify tick locations to match desired ticklabels
#cbar = fig.colorbar(fig, ticks=[np.min(colorv), np.max(colorv)])
#cb = plt.colorbar()
plt.show()

А затем с участием сетки ...

из сетки импорта данных matplotlib.mlab

r = np.arange(50)/5.
rstep = r[1] - r[0]
theta = np.arange(50)/50.*1.5*np.pi - np.pi
tstep = theta[1] - theta[0]
colorv = np.sin(r/10.*np.pi)

# force square figure and square axes looks better for polar, IMO
width, height = mpl.rcParams['figure.figsize']
size = min(width, height)
# make a square figure
fig = figure(figsize=(size, size))
ax = fig.add_axes([0.1, 0.1, .8, .8])#, polar=True)

my_cmap = cm.jet

x = r*np.cos(theta)
y = r*np.sin(theta)
X,Y = np.meshgrid(x,y)

data = griddata(x,y,colorv,X,Y)
cax = plt.contourf(X,Y, data)
plt.colorbar()

# Add colorbar, make sure to specify tick locations to match desired ticklabels
#cbar = fig.colorbar(fig, ticks=[np.min(colorv), np.max(colorv)])
#cb = plt.colorbar()
plt.show()

Ответы [ 2 ]

7 голосов
/ 19 января 2012

colorbar необходимо, чтобы вещи были экземпляром ScalarMappable, чтобы сделать из них цветную полосу.

Поскольку вы вручную настраиваете каждую плитку, нет ничего, что по существу имеет цветную полосу.

Есть несколько способов подделать его из вашей цветовой карты, но в этом случае есть гораздо более простое решение.

pcolormesh делает именно то, что вы хотите, и будет намного быстрее.

Как пример:

import numpy as np
import matplotlib.pyplot as plt

# Linspace makes what you're doing _much_ easier (and includes endpoints)
r = np.linspace(0, 10, 50)
theta = np.linspace(0, 2*np.pi, 50)

fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')

# "Grid" r and theta into 2D arrays (see the docs for meshgrid)
r, theta = np.meshgrid(r, theta)
cax = ax.pcolormesh(theta, r, r, edgecolors='black', antialiased=True)

# We could just call `plt.colorbar`, but I prefer to be more explicit
# and pass in the artist that I want it to extract colors from.
fig.colorbar(cax)

plt.show()

enter image description here

Или, если вы предпочитаете неполярные оси, как в примере кода:

import numpy as np
import matplotlib.pyplot as plt

r = np.linspace(0, 10, 50)
theta = np.linspace(0, 2*np.pi, 50)

# "Grid" r and theta and convert them to cartesian coords...
r, theta = np.meshgrid(r, theta)
x, y = r * np.cos(theta), r * np.sin(theta)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis('equal')

cax = ax.pcolormesh(x, y, r, edgecolors='black', antialiased=True)

fig.colorbar(cax)

plt.show()

enter image description here

Примечание. Если вы предпочитаете, чтобы граничные линии были немного менее темными, просто укажите linewidth=0.5 или что-то похожее на pcolormesh.

Наконец, если вы хотите напрямую создать цветовую полосу из цветовой карты в исходном коде, вы создадите из нее экземпляр ScalarMappable и передадите ее в colorbar. Это проще, чем кажется, но немного многословно.

Например, в исходном коде, если вы делаете что-то вроде следующего:

cax = cm.ScalarMappable(cmap=my_cmap)
cax.set_array(colorv)
fig.colorbar(cax)

Он должен делать то, что вы хотите.

1 голос
/ 20 января 2012

Итак, я нашел обходной путь. Поскольку я знаю регион, в котором у меня точно не будет данных, я их там подготовил. Я убедился, что данные охватывают весь диапазон того, что я собираю. Затем я прикрываю это (этот регион все равно должен был быть покрыт, он показывает, где находится «земля»). Теперь я могу пойти дальше и использовать plt.fill, как я делал изначально, и использовать цветную полосу из случайно выбранных данных. Я знаю, что это, вероятно, не правильный путь, но он работает и не пытается интерполировать мои данные.

Большое спасибо за помощь в сортировке. и если вы знаете о лучшем способе, я был бы рад услышать это!

hid = plt.pcolormesh(X,Y, data, antialiased=True)

#here we cover up the region that we just plotted in
r3 = [1 for i in range(360)]
theta3 = np.arange(360)*np.pi/180.
plt.fill(theta3, r3, 'w')

#now we can go through and fill in all the regions
for j in range(len(r)):
    rbox = np.array([r[j], r[j], r[j]+ rstep, r[j] + rstep])
    for i in range(len(theta)):
        thetabox = np.array([theta[i], theta[i] + tstep, theta[i] + tstep, theta[i]])
        x = rbox*np.cos(thetabox)
        y = rbox*np.sin(thetabox)
        colorv = np.sin(r[j]/10.*np.pi)
        plt.fill(thetabox,rbox, facecolor = my_cmap(colorv))
#And now we can plot the color bar that fits the data Tada :)
plt.colorbar()
plt.show()

Output of above code

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...