Fausto Arinos Barbuto
Fausto Arinos Barbuto

Reputation: 388

Why the structure of Matplotlib's color maps differ?

I am able to plot the RGB components of some Matplotlib's colour maps with this simple Python script:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap

mapa = cm.get_cmap('viridis', 256)

R = []; G = []; B = []

ind = np.linspace(1,256,256)

for item in mapa.colors:
    R.append(item[0])
    G.append(item[1])
    B.append(item[2])
    
plt.figure(1,figsize=(8,8))

plt.plot(ind,R,'r-')
plt.plot(ind,G,'g-')
plt.plot(ind,B,'b-')

plt.xlabel('$Colour \\ index$', fontsize=16, fontname="Times")
plt.ylabel('$RGB \\ component \\ weight$', fontsize=16, fontname="Times")

plt.show()

Some, but not all. It works OK with 'viridis', but not with the notorious 'jet', or 'prism', or 'summer' colour maps. This happens because (it seems) those maps do not have the attribute 'colors':

runfile('F:/Documents/Programs/Python/Colourmap_Plot.py', wdir='F:/Documents/Programs/Python') Traceback (most recent call last):

File "F:\Documents\Programs\Python\Colourmap_Plot.py", line 37, in for item in mapa.colors:

AttributeError: 'LinearSegmentedColormap' object has no attribute 'colors'

I wonder why that happens. Shouldn't all maps be equal with regard to their structure? How could I tell maps that do have the 'colors' attribute from the ones that haven't? And finally, how to plot the components from one of those 'non-conforming' maps?

Upvotes: 4

Views: 5173

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339052

There are two types of colormaps in matplotlib

  • ListedColormaps
  • LinearSegmentedColormaps

ListedColormaps are basically a list of colors. You get the number of colors via cmap.N and you get the colors themselves via cmap.colors.

LinearSegmentedColormaps are defined by interpolation. They store some sampling points in a dictionary and may interpolate between those, depending on the number of colors needed. The current number of colors is equally accessible via cmap.N.

Shouldn't all maps be equal with regard to their structure?

I guess they should. At least LinearSegmentedColormaps should expose a .colors attribute as well.

How could I tell maps that do have the 'colors' attribute from the ones that haven't?

You can to type or instance comparisson.

if isinstance(cmap, matplotlib.colors.LinearSegmentedColormap):
    # do something
    print("Is a segmented map")
elif isinstance(cmap, matplotlib.colors.ListedColormap):
    # do something else
    print("Is a listed map")

You can also check if the attribute exists,

if hasattr(cmap, "colors"):
    print("Is a listed map")
else:
    print("Is either not a colormap, or is a segmented one.")

And finally, how to plot the components from one of those 'non-conforming' maps?

A possible option to get the colors from a colormap, independent of their type would be to call the colormap with a list/array of integers, effectively indexing all colors up to cmap.N:

colors = cmap(np.arange(0,cmap.N)) 

colors is now a N by 4 shaped array of RGBA colors of the map.

Upvotes: 5

Related Questions