Pobieranie poszczególnych kolorów z mapy kolorów w matplotlib

136

Jeśli masz Colormap cmap, na przykład:

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

Jak uzyskać z niej określony kolor między 0 a 1, gdzie 0 to pierwszy kolor na mapie, a 1 to ostatni kolor na mapie?

Idealnie byłbym w stanie uzyskać środkowy kolor na mapie, wykonując:

>>> do_some_magic(cmap, 0.5) # Return an RGBA tuple
(0.1, 0.2, 0.3, 1.0)
LondonRob
źródło

Odpowiedzi:

219

Możesz to zrobić za pomocą poniższego kodu, a kod w twoim pytaniu był w rzeczywistości bardzo zbliżony do tego, czego potrzebujesz, wszystko, co musisz zrobić, to wywołać cmapobiekt, który masz.

import matplotlib

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

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

W przypadku wartości spoza zakresu [0.0, 1.0] zwróci odpowiednio kolor pod i nad. Domyślnie jest to minimalny i maksymalny kolor w zakresie (czyli 0,0 i 1,0). To ustawienie domyślne można zmienić za pomocą cmap.set_under()i cmap.set_over().

W przypadku liczb „specjalnych”, takich jak np.nani np.infdomyślnie używana jest wartość 0,0, można to zmienić za pomocą cmap.set_bad()podobnie jak poniżej i powyżej, jak powyżej.

Wreszcie może być konieczne znormalizowanie danych, aby były zgodne z zakresem [0.0, 1.0]. Można to zrobić w matplotlib.colors.Normalizeprosty sposób, jak pokazano w małym przykładzie poniżej, w którym argumenty vmini vmaxopisują, jakie liczby powinny być odwzorowane odpowiednio na 0,0 i 1,0.

import matplotlib

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

print(norm(15.0)) # 0.5

Normalizator logarytmiczny ( matplotlib.colors.LogNorm ) jest również dostępny dla zakresów danych z dużym zakresem wartości.

(Dziękuję zarówno Joe Kingtonowi, jak i tcaswell za sugestie, jak poprawić odpowiedź.)

Ffisegydd
źródło
3
W rzeczywistości dla wartości mniejszych niż 0 lub większych niż 1 zwróci kolor „powyżej” lub „poniżej”. Domyślnie jest to kolor na dole / na górze mapy kolorów, ale można to zmienić. Na przykład: cmap.set_under('red'); print cmap(0.0), cmap(-0.01)
Joe Kington
Cześć @Joe, dzięki za korektę, zmodyfikowałem odpowiedź :)
Ffisegydd
Istnieje również, set_badktóre określają, co robi dla np.nani np.infiirc. Powinieneś Normalizetu również wspomnieć o metodach.
tacaswell
12
Bardzo przydatne informacje i dlaczego u licha nie można tego znaleźć w dokumentacji!?!
Jaap Eldering
10
Jeśli to nie działa dla nikogo, a widzisz module 'matplotlib' has no attribute 'cm', spróbuj zamienić pierwsze dwa wiersze naimport matplotlib.pyplot as plt; cmap = plt.cm.get_cmap('Spectral')
Anonimowy
9

Aby uzyskać wartość całkowitą rgba zamiast wartości zmiennoprzecinkowej, możemy to zrobić

rgba = cmap(0.5,bytes=True)

Tak więc, aby uprościć kod na podstawie odpowiedzi z Ffisegydd, kod wyglądałby tak:

#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
amaliammr
źródło
0

Aby zbudować na rozwiązaniach Ffisegydd i amaliammr , oto przykład, w którym tworzymy reprezentację CSV dla niestandardowej mapy kolorów:

#! /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]))
Morten
źródło
0

Dla kompletności są to wybory cmap, z którymi do tej pory spotkałem:

Accent, Accent_r, Blues, Blues_r, BrBG, BrBG_r, BuGn, BuGn_r, BuPu, BuPu_r, CMRmap, CMRmap_r, Dark2, Dark2_r, GnBu, GnBu_r, Greens, Greens_r, Greys, Greys_r, ORGr, Orranges, Orranges PRGn_r, Paired, Paired_r, Pastel1, Pastel1_r, Pastel2, Pastel2_r, PiYG, PiYG_r, PuBu, PuBuGn, PuBuGn_r, PuBu_r, PuOr, PuOr_r, PuRd, PuRd_r, Purples, PuruGn_r, PuBu_r, PuRd, PuRd_r, Purples, PuruGn_r, RdByr, RdByr, RdByr, RdByr, RdByr RdYlBu, RdYlBu_r, RdYlGn, RdYlGn_r, Reds, Reds_r, Set1, Set1_r, Set2, Set2_r, Set3, Set3_r, Spectral, Spectral_r, Wistia, Wistia_r, YlGn, YlGnBu, YrGnBu, YrBlOr, YrBlOr, YrOr, Yr, Yr, Yr, Yr, Yr, Yr, Yr, Yr, Yr, B afmhot_r, autumn, autumn_r, binary, binary_r, bone, bone_r, brg, brg_r, bwr, bwr_r, cividis, cividis_r, cool, cool_r, coolwarm, coolwarm_r, copper, copper_r, cubehelix, cubehelix_r, flag, flag_r, gist_earth_r,gist_gray, gist_gray_r, gist_heat, gist_heat_r, gist_ncar, gist_ncar_r, gist_rainbow, gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg, gist_yarg_r, gnuplot, gnuplot2_nu_s, gist_rainbow_r, gist_stern, gist_stern_r, gist_yarg, gist_yarg_r, gnuplot, gnuplot2_nu_n jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, różowy, pink_r, plazma, plazma_r, pryzmat, prism_r, tęcza, tęcza_r, sejsmiczna, sejsmiczna_r, wiosna, wiosna_r, lato, lato_r, tab10, tab10_r, tab20, tab10, tab10_r, tab20 tab20b, tab20b_r, tab20c, tab20c_r, terrain, terrain_r, twilight, twilight_r, twilight_shifted, twilight_shifted_r, viridis, viridis_r, winter, winter_rgray_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, różowy, różowy_r, plazma, plazma_r, pryzmat, prism_r, tęcza, tęcza_rism, sejsmika wiosna, wiosna_r, lato, lato_r, tab10, tab10_r, tab20, tab20_r, tab20b, tab20b_r, tab20c, tab20c_r, teren, teren_r, zmierzch, twilight_r, twilight_shifted, twilight_shifted_r, viridis, viridis_r, zima, zima, zimagray_r, hot, hot_r, hsv, hsv_r, inferno, inferno_r, jet, jet_r, magma, magma_r, nipy_spectral, nipy_spectral_r, ocean, ocean_r, różowy, różowy_r, plazma, plazma_r, pryzmat, prism_r, tęcza, tęcza_rism, sejsmika wiosna, wiosna_r, lato, lato_r, tab10, tab10_r, tab20, tab20_r, tab20b, tab20b_r, tab20c, tab20c_r, teren, teren_r, zmierzch, twilight_r, twilight_shifted, twilight_shifted_r, viridis, viridis_r, zima, zima, zimaviridis, viridis_r, zima, zima_rviridis, viridis_r, zima, zima_r

prosti
źródło