【问题标题】:Partially discrete colormap matplotlib部分离散的颜色图 matplotlib
【发布时间】:2021-07-24 13:21:47
【问题描述】:

虽然有许多离散颜色图的示例(abc),但我想做一些不同的事情。我想要一个 3D 曲面图,它在小值和零之间具有鲜明的对比,因此颜色“跳跃”或颜色图是部分离散的。我这样做的原因是我想更清楚地区分小值和情节中被认为是“零”的值。

我正在生成一个 3D 曲面图并希望使用颜色图(如 'terrain')来指示 Z 轴上的高度。但是,我希望颜色图中有一个“间隙”,以突出显示与z=0 足够远的值。具体来说,假设z<1e-6 是颜色图的底部阈值(例如,深蓝色表示地形),但任何高于该阈值的值都位于颜色图的中间(例如,绿色表示地形)。

下面是一个简单的例子和​​对应的输出

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt

y = np.linspace(-3, 3, 100)
x = np.linspace(-3, 3, 100)
z = np.zeros(shape=(x.shape[0], y.shape[0]))

for i in range(x.shape[0]):
    # creating some generic Z-axis data
    z[:, i] = norm.pdf(y, loc=0, scale=0.2+(i/100))
    z[:, i] = z[:, i] / np.sum(z[:, i])  # normalizing

z = np.where(z < 1e-6, 0, z)  # setting 'small enough' threshold

x_mat, y_mat = np.meshgrid(x, y)

f1 = plt.axes(projection='3d')
f1.plot_surface(x_mat, y_mat, z, cmap='terrain', edgecolor='none', rstride=1)
plt.show()

这是上面的输出:

我希望输出看起来像所有“浅蓝色”区域都会变成绿色。一旦低于定义的阈值(此处为1e-6),颜色就会跳到深蓝色(因此没有区域会是浅蓝色)。

【问题讨论】:

标签: python matplotlib


【解决方案1】:

好的,我找到了解决我自己问题的方法。我改编了HERE 的解决方案来解决我的问题。以下是完成此操作的代码。

设置:

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
from matplotlib.cm import get_cmap

y = np.linspace(-3, 3, 100)
x = np.linspace(-3, 3, 100)
z = np.zeros(shape=(x.shape[0], y.shape[0]))

x_mat, y_mat = np.meshgrid(x, y)

# Threshold to apply
z_threshold = 1e-6


for i in range(x.shape[0]):
    z[:, i] = norm.pdf(y, loc=0, scale=0.2+(i/100))
    z[:, i] = z[:, i] / np.sum(z[:, i])  # normalizing

接下来我定义了两个不同的颜色图。第一个颜色图适用于高于阈值的所有值。如果值低于阈值,则将该正方形设置为透明。

cmap = get_cmap('terrain')
# 1.8 and 0.2 are used to restrict the upper and lower parts of the colormap
colors = cmap((z - z_threshold) / ((np.max(z)*1.8) - (np.min(z))) + 0.2)
# if below threshold, set as transparent (alpha=0)
colors[z < z_threshold, -1] = 0

第二个颜色图定义了低于阈值的所有位置的颜色。这一步不是完全必要的,但它确实可以防止平面被绘制在绘图的其余部分下方。

colors2 = cmap(z)
colors2[z >= z_threshold, -1] = 0

现在可以在两个 3D 绘图调用中使用颜色图

# init 3D plot
f1 = plt.axes(projection='3d')
# Plot values above the threshold
f1.plot_surface(x_mat, y_mat, z, facecolors=colors, edgecolor='none', rstride=1)
# Plot values below the threshold
z_below = np.zeros(shape=(x.shape[0], y.shape[0]))
f1.plot_surface(x_mat, y_mat, z_below,
                facecolors=colors2, edgecolor='none', rstride=1, vmin=0)
# Setting the zlimits
f1.set_zlim([0, np.max(z)])
plt.show()

以上结果如下图

【讨论】:

    猜你喜欢
    • 2014-12-20
    • 2013-11-19
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2014-09-10
    • 2011-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多