Логарифмическая карта цветов matplotlib для логарифмического графика поверхности

Я использую 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') 

вы можете предоставить фиктивные данные, чтобы помочь другим ответить вам.

Ahmed AEK 25.11.2022 11:59

если вы делаете логарифмическую цветовую шкалу, не логарифмируйте данные... Во-вторых, установите vmin на Z_min вместо очень маленького значения 1e-15. К сожалению, у меня нет метода ax.plot_surface, но я пробовал с ax.pcolormesh.

msi_gerva 25.11.2022 12:17

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

GKelly 25.11.2022 12:21

Я обновил код, чтобы грубо воспроизвести: вы можете видеть, что график сохраняет единственный цвет в диапазоне от 1e-11 до 1e-15, использование Z_min вызовет ошибку из-за отрицательного значения. На самом деле у X около 400 баллов, а у Y 1600.

GKelly 25.11.2022 12:34
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
4
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Редактировать: чтобы решить вашу проблему, вы берете журнал данных, а затем снова берете его при расчете нормы, просто удалите норму и примените 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-пространстве (как только я устранил отрицательные значения, как упомянул Ахмед.

GKelly 25.11.2022 12:58

Другие вопросы по теме