简体   繁体   中英

Why the structure of Matplotlib's colour 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?

Thanks.

There are two types of colormaps in matplotlib

  • ListedColormap s
  • LinearSegmentedColormap s

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

LinearSegmentedColormap s 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 LinearSegmentedColormap s 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM