从matplotlib中的颜色Map表获取单个颜色

zd287kbt  于 2023-01-31  发布在  其他
关注(0)|答案(7)|浏览(196)

例如,如果您有Colormapcmap

cmap = matplotlib.cm.get_cmap('Spectral')

你怎样才能得到一个特定的颜色从它之间的0和1,其中0是第一个颜色在Map和1是最后的颜色在Map上?
理想情况下,我可以通过以下操作获得Map中的中间颜色:

>>> do_some_magic(cmap, 0.5) # Return an RGBA tuple
(0.1, 0.2, 0.3, 1.0)
fzsnzjdm

fzsnzjdm1#

您可以使用下面的代码来完成此操作,并且您问题中的代码实际上非常接近您所需要的内容,您所要做的就是调用现有的cmap对象。

import matplotlib

cmap = matplotlib.cm.get_cmap('Spectral')

rgba = cmap(0.5)
print(rgba) # (0.99807766255210428, 0.99923106502084169, 0.74602077638401709, 1.0)

对于范围[0.0,1.0]之外的值,它将(分别)返回底色和底色。默认情况下,这是范围内的最小和最大颜色(即0.0和1.0)。此默认值可以用cmap.set_under()cmap.set_over()更改。
对于np.nannp.inf等“特殊”数字,默认值为0.0,可以使用cmap.set_bad()进行更改,类似于上述的上下。
最后,您可能需要规范化数据,使其符合范围[0.0, 1.0]。这可以使用matplotlib.colors.Normalize来完成,如下面的小示例所示,其中参数vminvmax分别描述了应该Map到0.0和1.0的数字。

import matplotlib

norm = matplotlib.colors.Normalize(vmin=10.0, vmax=20.0)

print(norm(15.0)) # 0.5

对数归一化器(matplotlib.colors.LogNorm)也可用于具有较大范围值的数据范围。

qjp7pelc

qjp7pelc2#

为了得到rgba的整数值而不是浮点值,我们可以做

rgba = cmap(0.5,bytes=True)

因此,为了根据Ffisegydd的答案简化代码,代码如下所示:

#import colormap
from matplotlib import cm

#normalize item number values to colormap
norm = matplotlib.colors.Normalize(vmin=0, vmax=1000)

#colormap possible values = viridis, jet, spectral
rgba_color = cm.jet(norm(400),bytes=True) 

#400 is one of value between 0 and 1000
ahy6op9u

ahy6op9u3#

我曾经遇到过一个类似的情况,我需要从一个颜色Map表的颜色"n"号,这样我就可以分配每种颜色给我的数据。我已经编译了一个代码,这个包称为"mycolorpy"。你可以pip安装它使用:

pip install mycolorpy

然后您可以执行以下操作:

from mycolorpy import colorlist as mcp
import numpy as np

示例:从cmap "winter"创建5个十六进制字符串的列表

color1=mcp.gen_color(cmap="winter",n=5)
print(color1)

输出:

['#0000ff', '#0040df', '#0080bf', '#00c09f', '#00ff80']

从cmap bwr生成16个颜色列表的另一个示例:

color2=mcp.gen_color(cmap="bwr",n=16)
print(color2)

输出:

['#0000ff', '#2222ff', '#4444ff', '#6666ff', '#8888ff', '#aaaaff', '#ccccff', '#eeeeff', '#ffeeee', '#ffcccc', '#ffaaaa', '#ff8888', '#ff6666', '#ff4444', '#ff2222', '#ff0000']

有一个带有用法示例的python notebook可以更好地形象化这一点。
假设你想从一个cmap中生成一个颜色列表,这个cmap被规范化为一个给定的数据,你可以使用:

a=random.randint(1000, size=(200))
a=np.array(a)
color1=mcp.gen_color_normalized(cmap="seismic",data_arr=a)
plt.scatter(a,a,c=color1)

输出:

也可以使用以下命令反转颜色:

color1=mcp.gen_color_normalized(cmap="seismic",data_arr=a,reverse=True)
plt.scatter(a,a,c=color1)

输出:

ryevplcw

ryevplcw4#

我正是遇到了这个问题,但我需要连续的图具有高度对比的颜色。我还使用包含参考数据的公共子图来绘制图,所以我希望颜色序列能够一致地重复。
我最初尝试简单地随机生成颜色,在每幅图之前重新植入RNG。这工作正常(在下面的代码中注解掉),但可能生成几乎无法区分的颜色。我想要高对比度的颜色,理想情况下从包含所有颜色的色图中采样。
我在一张图中可以有多达31个数据序列,所以我把色彩Map图分成了这么多个步骤,然后我按照一定的顺序执行这些步骤,以确保我不会很快回到给定颜色的邻域。
我的数据是在一个高度不规则的时间序列,所以我想看到的点和线,与点有'相反'的颜色的线。
考虑到上述所有情况,最简单的方法是生成一个字典,其中包含用于绘制单个序列的相关参数,然后将其作为调用的一部分展开。
这是我的代码,也许不漂亮,但功能齐全。

from matplotlib import cm
cmap = cm.get_cmap('gist_rainbow')  #('hsv') #('nipy_spectral')

max_colors = 31   # Constant, max mumber of series in any plot.  Ideally prime.
color_number = 0  # Variable, incremented for each series.

def restart_colors():
    global color_number
    color_number = 0
    #np.random.seed(1)

def next_color():
    global color_number
    color_number += 1
    #color = tuple(np.random.uniform(0.0, 0.5, 3))
    color = cmap( ((5 * color_number) % max_colors) / max_colors )
    return color

def plot_args():  # Invoked for each plot in a series as: '**(plot_args())'
    mkr = next_color()
    clr = (1 - mkr[0], 1 - mkr[1], 1 - mkr[2], mkr[3])  # Give line inverse of marker color
    return {
        "marker": "o",
        "color": clr,
        "mfc": mkr,
        "mec": mkr,
        "markersize": 0.5,
        "linewidth": 1,
    }

我的上下文是JupyterLab和Pandas,所以下面是示例图代码:

restart_colors()  # Repeatable color sequence for every plot

fig, axs = plt.subplots(figsize=(15, 8))
plt.title("%s + T-meter"%name)

# Plot reference temperatures:
axs.set_ylabel("°C", rotation=0)
for s in ["T1", "T2", "T3", "T4"]:
    df_tmeter.plot(ax=axs, x="Timestamp", y=s, label="T-meter:%s" % s, **(plot_args()))

# Other series gets their own axis labels
ax2 = axs.twinx()
ax2.set_ylabel(units)

for c in df_uptime_sensors:
    df_uptime[df_uptime["UUID"] == c].plot(
        ax=ax2, x="Timestamp", y=units, label="%s - %s" % (units, c), **(plot_args())
    )

fig.tight_layout()
plt.show()

生成的图可能不是最佳示例,但在交互放大时会变得更加相关。

whitzsjs

whitzsjs5#

为了在Ffisegyddamaliammr解决方案的基础上构建,下面是一个示例,我们为自定义色彩Map表创建CSV表示:

#! /usr/bin/env python3
import matplotlib
import numpy as np 

vmin = 0.1
vmax = 1000

norm = matplotlib.colors.Normalize(np.log10(vmin), np.log10(vmax))
lognum = norm(np.log10([.5, 2., 10, 40, 150,1000]))

cdict = {
    'red':
    (
        (0., 0, 0),
        (lognum[0], 0, 0),
        (lognum[1], 0, 0),
        (lognum[2], 1, 1),
        (lognum[3], 0.8, 0.8),
        (lognum[4], .7, .7),
    (lognum[5], .7, .7)
    ),
    'green':
    (
        (0., .6, .6),
        (lognum[0], 0.8, 0.8),
        (lognum[1], 1, 1),
        (lognum[2], 1, 1),
        (lognum[3], 0, 0),
        (lognum[4], 0, 0),
    (lognum[5], 0, 0)
    ),
    'blue':
    (
        (0., 0, 0),
        (lognum[0], 0, 0),
        (lognum[1], 0, 0),
        (lognum[2], 0, 0),
        (lognum[3], 0, 0),
        (lognum[4], 0, 0),
    (lognum[5], 1, 1)
    )
}

mycmap = matplotlib.colors.LinearSegmentedColormap('my_colormap', cdict, 256)   
norm = matplotlib.colors.LogNorm(vmin, vmax)
colors = {}
count = 0
step_size = 0.001
for value in np.arange(vmin, vmax+step_size, step_size):
    count += 1
    print("%d/%d %f%%" % (count, vmax*(1./step_size), 100.*count/(vmax*(1./step_size))))
    rgba = mycmap(norm(value), bytes=True)
    color = (rgba[0], rgba[1], rgba[2])
    if color not in colors.values():
        colors[value] = color

print ("value, red, green, blue")
for value in sorted(colors.keys()):
    rgb = colors[value]
    print("%s, %s, %s, %s" % (value, rgb[0], rgb[1], rgb[2]))
6ljaweal

6ljaweal6#

色彩Map表自带归一化方法,因此如果您已经绘制了图,则可以访问特定值的颜色。

import matplotlib.pyplot as plt
import numpy as np

cmap = plt.cm.viridis

cm = plt.pcolormesh(np.random.randn(10, 10), cmap=cmap)

print(cmap(cm.norm(2.2)))
s2j5cfk0

s2j5cfk07#

如果你想玩得又快又脏,你可以直接使用Map,或者你也可以按照@amaliammr说的去做。

data_size = 23   # range 0..23
colors = plt.cm.turbo
color_normal = colours.N/data_size

for i in range(data_size):
    col = colours.colors[int(i*color_normal)]

相关问题