sanjeev mk
sanjeev mk

Reputation: 4336

Getting "n" equally spaced RGB colors for "n" numbers, from a colormap

I have list of numbers, and want to assign a color for each of them from the ylorbr colormap in python. If my intuition of a colormap is correct, its just a range of colors - so, ylorbr goes from yellow to orange to brown.

I just want to get n equally spaced tuples of colors from this colormap, starting from 0 (in this case, that is yellow).

This is the simple code I tried:

from matplotlib import cm
import numpy as np
ylorbr = cm.get_cmap('YlOrBr', 8)
x = ylorbr(np.arange(0,1,0.1))

print(x)

When I try this, x is not a set of evenly spaced colors - in fact, colors are repeated. I also could not find other solutions for this - or there may be, but I am new to plotting.

I am new to plotting, but not new to python. Is there a reason, why getting a simple list of evenly spaced RGB from a given colormap is hard? I used "python sense" to do the above test, and actually expected an evenly spaced list of RGB tuples.

Can someone tell me how then a colormap works in python, and how to simply assign n sorted integers to n colors from a colormap in the shortest way possible?

Edit : I assumed here, that colormap is a discrete list of colors. I just want the first item , last item and every item at 1/n of that list of colors.

Edit2 : Based on Mark's comment below, I tried to access the list of colors of a map using the .colors attribute after get_cmap. But while it works when the colormap is viridis, it does not work when I set it to YlOrBr and I get the error : 'LinearSegmentedColormap' object has no attribute 'colors'

Upvotes: 2

Views: 3871

Answers (2)

denis
denis

Reputation: 21947

Colormaps have a resampled function, about what you want
(but interpolating in RGB space can give you ugly colors, make color connoisseurs cry)

#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as pl
from matplotlib.colors import Colormap, ListedColormap, LinearSegmentedColormap  # ? in ipython

def cmaparray( cmap: Colormap ) -> "N x 3 rgb array":
    # only ListedColormap has .colors, this works for both Listed and Linseg
    return cmap( np.linspace( 0, 1, cmap.N )) [:,:3]

def printcmap( cmap: Colormap ):
    print( f"{cmap.name}  len {cmap.N}:" )
    print( cmaparray( cmap ).T, "\n" )
    
#...............................................................................
if __name__ == "__main__":
    np.set_printoptions( precision=2 )
    print( 80 * "▄" )

    cmapname = "YlOrBr"  # Linseg
    # cmapname = "viridis"  # ListedColormap
    nin = 8
    nout = 10
    print( f"params: {cmapname = }  {nin = }  {nout = } \n" )

    cmap = pl.get_cmap( cmapname, nin )  # ListedColormap / LinearSegmentedColormap
    printcmap( cmap )

    sample = cmap.resampled( nout )  # does np.interp ? no dups
    sample.name = "sample"
    printcmap( sample )

Upvotes: 0

Tim Roberts
Tim Roberts

Reputation: 54698

You asked it to make a colormap with 8 entries. It shouldn't be surprising that you get repeats when you ask for 10 results.

I can hear you screaming "arrgggh" from here.

Upvotes: 3

Related Questions