Я использую python для создания карты 3D-поверхности, у меня есть массив данных, которые я пытаюсь построить как 3D-поверхность, проблема в том, что я зарегистрировал ось Z (необходимую для отображения пиков данных), что означает цветовая карта по умолчанию не работает (отображает один непрерывный цвет). Я пытался использовать LogNorm для нормализации цветовой карты, но опять же это дает один непрерывный цвет. Я не уверен, следует ли мне использовать зарегистрированные значения для нормализации карты, но если я сделаю это, максимальное значение будет отрицательным и выдаст ошибку?
fig=plt.figure(figsize=(10,10))
ax=plt.axes(projection='3d')
def log_tick_formatter(val, pos=None):
return "{:.2e}".format(10**val)
ax.zaxis.set_major_formatter(mticker.FuncFormatter(log_tick_formatter))
X=np.arange(0,2,1)
Y=np.arange(0,3,1)
X,Y=np.meshgrid(X,Y)
Z=[[1.2e-11,1.3e-11,-1.8e-11],[6e-13,1.3e-13,2e-15]]
Z_min=np.amin(Z)
Z_max=np.amax(Z)
norm = colors.LogNorm(vmin=1e-15,vmax=(Z_max),clip=False)
ax.plot_surface(X,Y,np.transpose(np.log10(Z)),norm=norm,cmap='rainbow')
если вы делаете логарифмическую цветовую шкалу, не логарифмируйте данные... Во-вторых, установите vmin на Z_min вместо очень маленького значения 1e-15. К сожалению, у меня нет метода ax.plot_surface, но я пробовал с ax.pcolormesh.
Я попытаюсь собрать некоторые фиктивные данные, мне просто нужно будет их размер, чтобы все имело смысл. Проблема с установкой Z_min на фактическое Z_min заключается в том, что это отрицательное значение, поэтому при логарифмировании возвращается nan.
Я обновил код, чтобы грубо воспроизвести: вы можете видеть, что график сохраняет единственный цвет в диапазоне от 1e-11 до 1e-15, использование Z_min вызовет ошибку из-за отрицательного значения. На самом деле у X около 400 баллов, а у Y 1600.
Редактировать: чтобы решить вашу проблему, вы берете журнал данных, а затем снова берете его при расчете нормы, просто удалите норму и примените vmin и vmax непосредственно к функции рисования
ax.plot_surface(X, Y, np.transpose(np.log10(Z)), cmap='rainbow',vmin=np.log10(1e-15),vmax=np.log10(Z_max))
вы можете использовать facecolor
аргумент plot_surface
, чтобы определить цвет для каждой грани независимо от z, вот упрощенный пример
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
x = np.linspace(0,10,100)
y = np.linspace(0,10,100)
x,y = np.meshgrid(x,y)
z = np.sin(x+y)
fig, ax = plt.subplots(subplot_kw = {"projection": "3d"})
cmap = matplotlib.cm.get_cmap('rainbow')
def rescale_0_to_1(item):
max_z = np.amax(item)
min_z = np.amin(item)
return (item - min_z)/(max_z-min_z)
rgba = cmap(rescale_0_to_1(z)) # some values of z to calculate color with
real_z = np.log(z+1) # real values of z to draw
surf = ax.plot_surface(x, y, real_z, cmap='rainbow', facecolors=rgba)
plt.show()
вы можете изменить его для расчета цветов на основе x или y или чего-то совершенно не связанного.
Просто пример логарифмических цветов и логарифмических данных:
#!/usr/bin/env ipython
import numpy as np
import matplotlib as mpl
import matplotlib.pylab as plt
import matplotlib.colors as colors
# ------------------
X=np.arange(0,401,1);nx= np.size(X)
Y=np.arange(40,200,1);ny = np.size(Y)
X,Y=np.meshgrid(X,Y)
Z = 10000*np.random.random((ny,nx))
Z=np.array(Z)
# ------------------------------------------------------------
Z_min=np.amin(Z)
Z_max=np.amax(Z)
# ------------------------------------------------------------
norm = colors.LogNorm(vmin=np.nanmin(Z),vmax=np.nanmax(Z),clip=False)
# ------------------------------------------------------------
fig = plt.figure(figsize=(15,5));axs = [fig.add_subplot(131),fig.add_subplot(132),fig.add_subplot(133)]
p0 = axs[0].pcolormesh(X,Y,np.log10(Z),cmap='rainbow',norm=norm);plt.colorbar(p0,ax=axs[0]);
axs[0].set_title('Original method: NOT TO DO!')
p1 = axs[1].pcolormesh(X,Y,Z,cmap='rainbow',norm=norm);plt.colorbar(p1,ax=axs[1])
axs[1].set_title('Normalized colorbar, original data')
p2 = axs[2].pcolormesh(X,Y,np.log10(Z),cmap='rainbow');plt.colorbar(p2,ax=axs[2])
axs[2].set_title('Logarithmic data, original colormap')
plt.savefig('test.png',bbox_inches='tight')
# --------------------------------------------------------------
Итак, результат такой:
В первом случае мы использовали логарифмическую карту цветов, а также взяли логарифм данных, поэтому цветовая полоса больше не работает, так как значения на карте малы, и мы использовали большие пределы для цветовой полосы. В среднем изображении мы используем нормализованную цветовую полосу или логарифмическую цветовую полосу, чтобы было вполне естественно понятно, что на изображении и какие значения. Третий случай — когда мы логарифмируем данные, а цветная полоса просто показывает степень 10-го, которую мы должны использовать для интерпретации окрашенного значения на графике.
Итак, в конце концов, я бы предложил средний метод: использовать логарифмическую цветовую шкалу и исходные данные.
Спасибо, это сработало для данных в 2D-пространстве (как только я устранил отрицательные значения, как упомянул Ахмед.
вы можете предоставить фиктивные данные, чтобы помочь другим ответить вам.