web-dev-qa-db-fra.com

Obtenir des couleurs individuelles d'une carte de couleurs dans matplotlib

Si vous avez une palette de couleurs de

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

comment obtenir une couleur particulière entre 0 et 1, où 0.0 est la première couleur de la carte et 1.0 la dernière de la carte?

Idéalement, je pourrais obtenir la couleur moyenne de la carte en faisant:

>>> do_some_magic(cmap, 0.5) # Return an RGBA tuplet
(0.1, 0.2, 0.3, 1.0)
93
LondonRob

Vous pouvez le faire avec le code ci-dessous, et le code de votre question était en réalité très proche de ce dont vous aviez besoin, il vous suffit d'appeler l'objet cmap que vous avez.

import matplotlib

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

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

Pour les valeurs situées en dehors de la plage [0.0, 1.0], les couleurs inférieure et supérieure sont renvoyées (respectivement). Ceci, par défaut, est la couleur minimum et maximum dans la plage (donc 0.0 et 1.0). Cette valeur par défaut peut être modifiée avec cmap.set_under() et cmap_set_over().

Pour les nombres "spéciaux" tels que np.nan Et np.inf, La valeur par défaut consiste à utiliser la valeur 0.0; vous pouvez la modifier à l'aide de cmap.set_bad() de la même manière que ci-dessus et plus bas.

Enfin, vous devrez peut-être normaliser vos données de manière à ce qu'elles se conforment à l'intervalle [0.0, 1.0]. Ceci peut être fait en utilisant matplotlib.colors.Normalize simplement comme indiqué dans le petit exemple ci-dessous où les arguments vmin et vmax décrivent quels nombres doivent être associés à 0.0 et 1,0 respectivement.

import matplotlib

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

print(norm(15.0)) # 0.5

Un normalisateur logarithmique ( matplotlib.colors.LogNorm ) est également disponible pour les plages de données avec une large plage de valeurs.

(Merci à la fois Joe Kington et tcaswell pour leurs suggestions sur la façon d'améliorer la réponse.)

160
Ffisegydd

Pour obtenir la valeur entière rgba au lieu de la valeur float, nous pouvons faire

rgba = cmap(0.5,bytes=True)

Donc, pour simplifier le code basé sur la réponse de Ffisegydd, le code ressemblerait à ceci:

#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
6
amaliammr

Pour tirer parti des solutions de Ffisegydd et amaliammr , voici un exemple où nous créons une représentation CSV pour une carte de couleurs personnalisée:

#! /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]))
0
Morten