Нормализация цветов в матплотлиб - PullRequest
5 голосов
/ 06 марта 2011

Я пытаюсь построить поверхность, используя matplotlib, используя следующий код:

from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p

vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))

surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, alpha=1,cmap=cm.jet,  linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

Если вы запустите его, вы увидите синюю поверхность, но я хочу использовать весь цветовой диапазон струи.Я знаю, что есть класс "matplotlib.colors.Normalize", но я не знаю, как его использовать.Не могли бы вы добавить необходимый код для этого?

Ответы [ 3 ]

18 голосов
/ 18 сентября 2012

Я понимаю, что проблема плаката уже решена, но вопрос нормализации цветов никогда не решался. Поскольку я понял, как я думал, я просто оставлю это здесь для всех, кому это может понадобиться.

Сначала вы создаете норму и передаете ее в функцию построения графиков. Я попытался добавить ее в код ОП.

from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p
import matplotlib

vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))
Z = np.nan_to_num(Z)

# Make the norm
norm = matplotlib.colors.Normalize(vmin = np.min(Z), vmax = np.max(Z), clip = False)

# Plot with the norm
surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, norm=norm, alpha=1,cmap=cm.jet,     linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

Норма работает аналогично команде "imshow".

4 голосов
/ 07 марта 2011

Как отметил ДжошАдель в комментарии (ему принадлежит кредит), кажется, что график поверхности неправильно масштабирует карту цветов, когда NaN находится в массиве Z.Простой обходной путь - просто преобразовать NaN в ноль или очень большие или очень маленькие числа, чтобы цветовую карту можно было нормализовать по диапазону оси z.

3 голосов
/ 30 декабря 2015

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

Во-первых, я не хотел использовать нули для замены NaN, поскольку для меня они представляют точки с отсутствующими или неопределенными данными. Я бы предпочел не иметь в этих точках ничего . Во-вторых, весь диапазон моих данных z был намного выше нуля, поэтому расставление точек с нулями привело бы к уродливому и плохо масштабированному графику.

Решение, данное Лейфденби, было довольно близко, так что +1 за это (хотя, как указывалось, явная нормализация не добавляет к более раннему решению). Я просто отбросил замену NaN на ноль и использовал функции nanmin и nanmax вместо min и max в нормализации цветовой шкалы. Эти функции дают минимальное и максимальное значения массива , но просто игнорируют все NaN . Код теперь гласит:

# Added colors to the matplotlib import list
from matplotlib import cm, colors
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import axes3d, Axes3D
import pylab as p


vima=0.5

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(0, 16.67, vima)
Y = np.arange(0, 12.5, vima)
X, Y = np.meshgrid(X, Y)

Z = np.sqrt(((1.2*Y+0.6*X)**2+(0.2*Y+1.6*X)**2)/(0.64*Y**2+0.36*X**2))

# MAIN IDEA: Added normalisation using nanmin and nanmax functions
norm = colors.Normalize(vmin = np.nanmin(Z), 
                        vmax = np.nanmax(Z))

# Added the norm=norm parameter
surf = ax.plot_surface(X, Y, Z,rstride=1, cstride=1, alpha=1, norm=norm, cmap=cm.jet,  linewidth=0)
fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()

Запустив это, я получаю правильно масштабированный график с отсутствующей точкой данных (0, 0). Это также поведение, которое я считаю наиболее предпочтительным, поскольку для рассматриваемой функции не существует предела (x, y) в (0, 0).

Это был мой первый вклад в StackOverflow, надеюсь, он был хорошим (подмигнул).

...