1010.. _palettable: https://jiffyclub.github.io/palettable/
1111
1212However, we often want to create or manipulate colormaps in Matplotlib.
13- This can be done using the class `.ListedColormap` and a Nx4 numpy array of
14- values between 0 and 1 to represent the RGBA values of the colormap. There
15- is also a `.LinearSegmentedColormap` class that allows colormaps to be
16- specified with a few anchor points defining segments, and linearly
17- interpolating between the anchor points.
13+ This can be done using the class `.ListedColormap` or
14+ `.LinearSegmentedColormap`.
15+ Seen from the outside, both colormap classes map values between 0 and 1 to
16+ a bunch of colors. There are, however, slight differences, some of which are
17+ shown in the following.
18+
19+ Before manually creating or manipulating colormaps, let us first see how we
20+ can obtain colormaps and their colors from existing colormap classes.
21+
1822
1923Getting colormaps and accessing their values
2024============================================
2125
2226First, getting a named colormap, most of which are listed in
23- :doc:`/tutorials/colors/colormaps` requires the use of
24- `.matplotlib.cm.get_cmap`, which returns a
25- :class:`.matplotlib.colors.ListedColormap` object. The second argument gives
26- the size of the list of colors used to define the colormap, and below we
27- use a modest value of 12 so there are not a lot of values to look at.
27+ :doc:`/tutorials/colors/colormaps`, may be done using
28+ `.matplotlib.cm.get_cmap`, which returns a colormap object.
29+ The second argument gives the size of the list of colors used to define the
30+ colormap, and below we use a modest value of 8 so there are not a lot of
31+ values to look at.
2832"""
2933
3034import numpy as np
3135import matplotlib .pyplot as plt
3236from matplotlib import cm
3337from matplotlib .colors import ListedColormap , LinearSegmentedColormap
3438
35- viridis = cm .get_cmap ('viridis' , 12 )
39+ viridis = cm .get_cmap ('viridis' , 8 )
3640print (viridis )
3741
3842##############################################################################
4246print (viridis (0.56 ))
4347
4448##############################################################################
49+ # ListedColormap
50+ # --------------
51+ #
52+ # `ListedColormap` s store their color values in a ``.colors`` attribute.
4553# The list of colors that comprise the colormap can be directly accessed using
4654# the ``colors`` property,
4755# or it can be accessed indirectly by calling ``viridis`` with an array
4856# of values matching the length of the colormap. Note that the returned list
4957# is in the form of an RGBA Nx4 array, where N is the length of the colormap.
5058
5159print ('viridis.colors' , viridis .colors )
52- print ('viridis(range(12 ))' , viridis (range (12 )))
53- print ('viridis(np.linspace(0, 1, 12 ))' , viridis (np .linspace (0 , 1 , 12 )))
60+ print ('viridis(range(8 ))' , viridis (range (8 )))
61+ print ('viridis(np.linspace(0, 1, 8 ))' , viridis (np .linspace (0 , 1 , 8 )))
5462
5563##############################################################################
5664# The colormap is a lookup table, so "oversampling" the colormap returns
5765# nearest-neighbor interpolation (note the repeated colors in the list below)
5866
59- print ('viridis(np.linspace(0, 1, 15))' , viridis (np .linspace (0 , 1 , 15 )))
67+ print ('viridis(np.linspace(0, 1, 12))' , viridis (np .linspace (0 , 1 , 12 )))
68+
69+ ##############################################################################
70+ # LinearSegmentedColormap
71+ # -----------------------
72+ # `LinearSegmentedColormap` s do not have a ``.colors`` attribute.
73+ # However, one may still call the colormap with an integer array, or with a
74+ # float array between 0 and 1.
75+
76+ copper = cm .get_cmap ('copper' , 8 )
77+ print (copper )
78+
79+ print ('copper(range(8))' , copper (range (8 )))
80+ print ('copper(np.linspace(0, 1, 8))' , copper (np .linspace (0 , 1 , 8 )))
6081
6182##############################################################################
6283# Creating listed colormaps
6384# =========================
6485#
65- # This is essential the inverse operation of the above where we supply a
66- # Nx4 numpy array with all values between 0 and 1,
67- # to `.ListedColormap` to make a new colormap. This means that
68- # any numpy operations that we can do on a Nx4 array make carpentry of
69- # new colormaps from existing colormaps quite straight forward.
86+ # Creating a colormap is essentially the inverse operation of the above where
87+ # we supply a list or array of color specifications to `.ListedColormap` to
88+ # make a new colormap.
7089#
71- # Suppose we want to make the first 25 entries of a 256-length "viridis"
72- # colormap pink for some reason:
90+ # Before continuing with the tutorial, let us define a helper function that
91+ # takes one of more colormaps as input, creates some random data and applies
92+ # the colormap(s) to an image plot of that dataset.
7393
74- viridis = cm .get_cmap ('viridis' , 256 )
75- newcolors = viridis (np .linspace (0 , 1 , 256 ))
76- pink = np .array ([248 / 256 , 24 / 256 , 148 / 256 , 1 ])
77- newcolors [:25 , :] = pink
78- newcmp = ListedColormap (newcolors )
7994
80-
81- def plot_examples (cms ):
82- """Helper function to plot two colormaps."""
95+ def plot_examples (colormaps ):
96+ """
97+ Helper function to plot data with associated colormap.
98+ """
8399 np .random .seed (19680801 )
84100 data = np .random .randn (30 , 30 )
85-
86- fig , axs = plt .subplots (1 , 2 , figsize = (6 , 3 ), constrained_layout = True )
87- for [ax , cmap ] in zip (axs , cms ):
101+ n = len (colormaps )
102+ fig , axs = plt .subplots (1 , n , figsize = (n * 2 + 2 , 3 ),
103+ constrained_layout = True , squeeze = False )
104+ for [ax , cmap ] in zip (axs .flat , colormaps ):
88105 psm = ax .pcolormesh (data , cmap = cmap , rasterized = True , vmin = - 4 , vmax = 4 )
89106 fig .colorbar (psm , ax = ax )
90107 plt .show ()
91108
109+
110+ ##############################################################################
111+ # In the simplest case we might type in a list of color names to create a
112+ # colormap from those.
113+
114+ cmap = ListedColormap (["darkorange" , "gold" , "lawngreen" , "lightseagreen" ])
115+ plot_examples ([cmap ])
116+
117+ ##############################################################################
118+ # In fact, that list may contain any valid
119+ # :doc:`matplotlib color specification </tutorials/colors/colors>`.
120+ # Particularly useful for creating custom colormaps are Nx4 numpy arrays.
121+ # Because with the variety of numpy operations that we can do on a such an
122+ # array, carpentry of new colormaps from existing colormaps become quite
123+ # straight forward.
124+ #
125+ # For example, suppose we want to make the first 25 entries of a 256-length
126+ # "viridis" colormap pink for some reason:
127+
128+ viridis = cm .get_cmap ('viridis' , 256 )
129+ newcolors = viridis (np .linspace (0 , 1 , 256 ))
130+ pink = np .array ([248 / 256 , 24 / 256 , 148 / 256 , 1 ])
131+ newcolors [:25 , :] = pink
132+ newcmp = ListedColormap (newcolors )
133+
92134plot_examples ([viridis , newcmp ])
93135
94136##############################################################################
@@ -113,14 +155,14 @@ def plot_examples(cms):
113155
114156##############################################################################
115157# Of course we need not start from a named colormap, we just need to create
116- # the Nx4 array to pass to `.ListedColormap`. Here we create a
117- # brown colormap that goes to white... .
158+ # the Nx4 array to pass to `.ListedColormap`. Here we create a
159+ # colormap that goes from brown (RGB: 90,40,40) to white (RGB: 255,255,255) .
118160
119161N = 256
120162vals = np .ones ((N , 4 ))
121163vals [:, 0 ] = np .linspace (90 / 256 , 1 , N )
122- vals [:, 1 ] = np .linspace (39 / 256 , 1 , N )
123- vals [:, 2 ] = np .linspace (41 / 256 , 1 , N )
164+ vals [:, 1 ] = np .linspace (40 / 256 , 1 , N )
165+ vals [:, 2 ] = np .linspace (40 / 256 , 1 , N )
124166newcmp = ListedColormap (vals )
125167plot_examples ([viridis , newcmp ])
126168
@@ -190,6 +232,27 @@ def plot_linearmap(cdict):
190232 [1.0 , 1.0 , 1.0 ]]
191233plot_linearmap (cdict )
192234
235+ #############################################################################
236+ # Directly creating a segmented colormap from a list
237+ # --------------------------------------------------
238+ #
239+ # The above described is a very versatile approach, but admitedly a bit
240+ # cumbersome to implement. For some basic cases, the use of
241+ # `LinearSegmentedColormap.from_list` may be easier. This creates a segmented
242+ # colormap with equal spacings from a supplied list of colors.
243+
244+ colors = ["darkorange" , "gold" , "lawngreen" , "lightseagreen" ]
245+ cmap1 = LinearSegmentedColormap .from_list ("mycmap" , colors )
246+
247+ #############################################################################
248+ # If desired, the nodes of the colormap can be given as numbers
249+ # between 0 and 1. E.g. one could have the reddish part take more space in the
250+ # colormap.
251+
252+ nodes = [0.0 , 0.4 , 0.8 , 1.0 ]
253+ cmap2 = LinearSegmentedColormap .from_list ("mycmap" , list (zip (nodes , colors )))
254+
255+ plot_examples ([cmap1 , cmap2 ])
193256
194257#############################################################################
195258#
0 commit comments