Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1f003b0

Browse files
authored
Merge pull request #14968 from ImportanceOfBeingErnest/doc-colormap-man-update
DOC: colormap manipulation tutorial update
2 parents 442049e + 7c080f4 commit 1f003b0

File tree

1 file changed

+99
-36
lines changed

1 file changed

+99
-36
lines changed

tutorials/colors/colormap-manipulation.py

Lines changed: 99 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,33 @@
1010
.. _palettable: https://jiffyclub.github.io/palettable/
1111
1212
However, 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
1923
Getting colormaps and accessing their values
2024
============================================
2125
2226
First, 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

3034
import numpy as np
3135
import matplotlib.pyplot as plt
3236
from matplotlib import cm
3337
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
3438

35-
viridis = cm.get_cmap('viridis', 12)
39+
viridis = cm.get_cmap('viridis', 8)
3640
print(viridis)
3741

3842
##############################################################################
@@ -42,53 +46,91 @@
4246
print(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

5159
print('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+
92134
plot_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

119161
N = 256
120162
vals = np.ones((N, 4))
121163
vals[:, 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)
124166
newcmp = ListedColormap(vals)
125167
plot_examples([viridis, newcmp])
126168

@@ -190,6 +232,27 @@ def plot_linearmap(cdict):
190232
[1.0, 1.0, 1.0]]
191233
plot_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

Comments
 (0)