Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c9a71f0

Browse filesBrowse files
timhoffmtacaswell
authored andcommitted
Merge pull request #11905 from jklymak/doc-add-colormap-manipulation
DOC: colormap-manipulation tutorial
1 parent 567333b commit c9a71f0
Copy full SHA for c9a71f0

File tree

Expand file treeCollapse file tree

5 files changed

+248
-11
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+248
-11
lines changed

‎.flake8

Copy file name to clipboardExpand all lines: .flake8
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ per-file-ignores =
9494
tutorials/advanced/transforms_tutorial.py: E402, E501
9595
tutorials/colors/colormaps.py: E501
9696
tutorials/colors/colors.py: E402
97+
tutorials/colors/colormap-manipulation.py: E402
9798
tutorials/intermediate/artists.py: E402, E501
9899
tutorials/intermediate/constrainedlayout_guide.py: E402
99100
tutorials/intermediate/gridspec.py: E402, E501
@@ -121,6 +122,7 @@ per-file-ignores =
121122
examples/color/color_demo.py: E402
122123
examples/color/colorbar_basics.py: E402
123124
examples/color/colormap_reference.py: E402
125+
examples/color/custom_cmap.py: E402
124126
examples/color/named_colors.py: E402
125127
examples/event_handling/data_browser.py: E501
126128
examples/event_handling/path_editor.py: E501
@@ -136,7 +138,6 @@ per-file-ignores =
136138
examples/images_contours_and_fields/contourf_demo.py: E402, E501
137139
examples/images_contours_and_fields/contourf_hatching.py: E402
138140
examples/images_contours_and_fields/contourf_log.py: E402
139-
examples/images_contours_and_fields/custom_cmap.py: E402
140141
examples/images_contours_and_fields/demo_bboximage.py: E402
141142
examples/images_contours_and_fields/image_clip_path.py: E402
142143
examples/images_contours_and_fields/image_demo.py: E402

‎examples/images_contours_and_fields/custom_cmap.py renamed to ‎examples/color/custom_cmap.py

Copy file name to clipboardExpand all lines: examples/color/custom_cmap.py
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
Creating a colormap from a list of colors
44
=========================================
55
6+
For more detail on creating and manipulating colormaps see
7+
:doc:`/tutorials/colors/colormap-manipulation`.
8+
69
Creating a :doc:`colormap </tutorials/colors/colormaps>`
710
from a list of colors can be done with the
811
:meth:`~.colors.LinearSegmentedColormap.from_list` method of

‎lib/matplotlib/cm.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cm.py
+15-2Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
11
"""
22
Builtin colormaps, colormap handling utilities, and the `ScalarMappable` mixin.
33
4-
See :doc:`/gallery/color/colormap_reference` for a list of builtin colormaps.
5-
See :doc:`/tutorials/colors/colormaps` for an in-depth discussion of colormaps.
4+
.. seealso::
5+
6+
:doc:`/gallery/color/colormap_reference` for a list of builtin
7+
colormaps.
8+
9+
:doc:`/tutorials/colors/colormap-manipulation` for examples of how to
10+
make colormaps and
11+
12+
:doc:`/tutorials/colors/colormaps` an in-depth discussion of
13+
choosing colormaps.
14+
15+
:doc:`/tutorials/colors/colormapnorms` for more details about data
16+
normalization
17+
18+
619
"""
720

821
import functools

‎lib/matplotlib/colors.py

Copy file name to clipboardExpand all lines: lib/matplotlib/colors.py
+19-8Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,25 @@
66
77
This module includes functions and classes for color specification
88
conversions, and for mapping numbers to colors in a 1-D array of colors called
9-
a colormap. Colormapping typically involves two steps: a data array is first
10-
mapped onto the range 0-1 using an instance of :class:`Normalize` or of a
11-
subclass; then this number in the 0-1 range is mapped to a color using an
12-
instance of a subclass of :class:`Colormap`. Two are provided here:
13-
:class:`LinearSegmentedColormap`, which is used to generate all the built-in
14-
colormap instances, but is also useful for making custom colormaps, and
15-
:class:`ListedColormap`, which is used for generating a custom colormap from a
16-
list of color specifications.
9+
a colormap.
10+
11+
Mapping data onto colors using a colormap typically involves two steps:
12+
a data array is first mapped onto the range 0-1 using a subclass of
13+
:class:`Normalize`, then this number is mapped to a color using
14+
a subclass of :class:`Colormap`. Two are provided here:
15+
:class:`LinearSegmentedColormap`, which uses piecewise-linear interpolation
16+
to define colormaps, and :class:`ListedColormap`, which makes a colormap
17+
from a list of colors.
18+
19+
.. seealso::
20+
21+
:doc:`/tutorials/colors/colormap-manipulation` for examples of how to
22+
make colormaps and
23+
24+
:doc:`/tutorials/colors/colormaps` for a list of built-in colormaps.
25+
26+
:doc:`/tutorials/colors/colormapnorms` for more details about data
27+
normalization
1728
1829
The module also provides functions for checking whether an object can be
1930
interpreted as a color (:func:`is_color_like`), for converting such an object
+209Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
"""
2+
********************************
3+
Creating Colormaps in Matplotlib
4+
********************************
5+
6+
Creating and manipulating colormaps in Matplotlib is straight-forward
7+
using the class `.ListedColormap` and a Nx4 numpy array of values
8+
between 0 and 1 to represent the RGBA values of the colormap. There
9+
is also a `.LinearSegmentedColormap` class that allows colormaps to be
10+
specified with far fewer anchor points defining segments, and linearly
11+
interpolating between the anchor points.
12+
13+
Getting colormaps and accessing their values
14+
============================================
15+
16+
First, getting a named colormap, most of which are listed in
17+
:doc:`/tutorials/colors/colormaps` requires the use of
18+
`.matplotlib.cm.get_cmap`, which returns a
19+
:class:`.matplotlib.colors.ListedColormap` object. The second argument gives
20+
the size of the list of colors used to define the colormap, and below we
21+
use a modest value of 12 so there are not a lot of values to look at.
22+
"""
23+
24+
import numpy as np
25+
import matplotlib as mpl
26+
import matplotlib.pyplot as plt
27+
from matplotlib import cm
28+
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
29+
from collections import OrderedDict
30+
31+
viridis = cm.get_cmap('viridis', 12)
32+
print(viridis)
33+
34+
##############################################################################
35+
# The object ``viridis`` is a callable, that when passed a float between
36+
# 0 and 1 returns an RGBA value from the colormap:
37+
38+
print(viridis(0.56))
39+
40+
##############################################################################
41+
# The list of colors that comprise the colormap can be directly accessed using
42+
# the ``colors`` property,
43+
# or it can be acccessed indirectly by calling ``viridis`` with an array
44+
# of values matching the length of the colormap. Note that the returned list
45+
# is in the form of an RGBA Nx4 array, where N is the length of the colormap.
46+
47+
print('viridis.colors', viridis.colors)
48+
print('viridis(range(12))', viridis(range(12)))
49+
print('viridis(np.linspace(0, 1, 12))', viridis(np.linspace(0, 1, 12)))
50+
51+
##############################################################################
52+
# The colormap is a lookup table, so "oversampling" the colormap returns
53+
# nearest-neighbor interpolation (note the repeated colors in the list below)
54+
55+
print('viridis(np.linspace(0, 1, 15))', viridis(np.linspace(0, 1, 15)))
56+
57+
##############################################################################
58+
# Creating listed colormaps
59+
# =========================
60+
#
61+
# This is essential the inverse operation of the above where we supply a
62+
# Nx4 numpy array with all values between 0 and 1,
63+
# to `.ListedColormap` to make a new colormap. This means that
64+
# any numpy operations that we can do on a Nx4 array make carpentry of
65+
# new colormaps from existing colormaps quite straight forward.
66+
#
67+
# Suppose we want to make the first 25 entries of a 256-length "viridis"
68+
# colormap pink for some reason:
69+
70+
viridis = cm.get_cmap('viridis', 256)
71+
newcolors = viridis(np.linspace(0, 1, 256))
72+
pink = np.array([248/256, 24/256, 148/256, 1])
73+
newcolors[:25, :] = pink
74+
newcmp = ListedColormap(newcolors)
75+
76+
77+
def plot_examples(cms):
78+
"""
79+
helper function to plot two colormaps
80+
"""
81+
np.random.seed(19680801)
82+
data = np.random.randn(30, 30)
83+
84+
fig, axs = plt.subplots(1, 2, figsize=(6, 3), constrained_layout=True)
85+
for [ax, cmap] in zip(axs, cms):
86+
psm = ax.pcolormesh(data, cmap=cmap, rasterized=True, vmin=-4, vmax=4)
87+
fig.colorbar(psm, ax=ax)
88+
plt.show()
89+
90+
plot_examples([viridis, newcmp])
91+
92+
##############################################################################
93+
# We can easily reduce the dynamic range of a colormap; here we choose the
94+
# middle 0.5 of the colormap. However, we need to interpolate from a larger
95+
# colormap, otherwise the new colormap will have repeated values.
96+
97+
viridisBig = cm.get_cmap('viridis', 512)
98+
newcmp = ListedColormap(viridisBig(np.linspace(0.25, 0.75, 256)))
99+
plot_examples([viridis, newcmp])
100+
101+
##############################################################################
102+
# and we can easily concatenate two colormaps:
103+
104+
top = cm.get_cmap('Oranges_r', 128)
105+
bottom = cm.get_cmap('Blues', 128)
106+
107+
newcolors = np.vstack((top(np.linspace(0, 1, 128)),
108+
bottom(np.linspace(0, 1, 128))))
109+
newcmp = ListedColormap(newcolors, name='OrangeBlue')
110+
plot_examples([viridis, newcmp])
111+
112+
##############################################################################
113+
# Of course we need not start from a named colormap, we just need to create
114+
# the Nx4 array to pass to `.ListedColormap`. Here we create a
115+
# brown colormap that goes to white....
116+
117+
N = 256
118+
vals = np.ones((N, 4))
119+
vals[:, 0] = np.linspace(90/256, 1, N)
120+
vals[:, 1] = np.linspace(39/256, 1, N)
121+
vals[:, 2] = np.linspace(41/256, 1, N)
122+
newcmp = ListedColormap(vals)
123+
plot_examples([viridis, newcmp])
124+
125+
##############################################################################
126+
# Creating linear segmented colormaps
127+
# ===================================
128+
#
129+
# `.LinearSegmentedColormap` class specifies colormaps using anchor points
130+
# between which RGB(A) values are interpolated.
131+
#
132+
# The format to specify these colormaps allows discontinuities at the anchor
133+
# points. Each anchor point is specified as a row in a matrix of the
134+
# form ``[x[i] yleft[i] yright[i]]``, where ``x[i]`` is the anchor, and
135+
# ``yleft[i]`` and ``yright[i]`` are the values of the color on either
136+
# side of the anchor point.
137+
#
138+
# If there are no discontinuities, then ``yleft[i]=yright[i]``:
139+
140+
cdict = {'red': [[0.0, 0.0, 0.0],
141+
[0.5, 1.0, 1.0],
142+
[1.0, 1.0, 1.0]],
143+
'green': [[0.0, 0.0, 0.0],
144+
[0.25, 0.0, 0.0],
145+
[0.75, 1.0, 1.0],
146+
[1.0, 1.0, 1.0]],
147+
'blue': [[0.0, 0.0, 0.0],
148+
[0.5, 0.0, 0.0],
149+
[1.0, 1.0, 1.0]]}
150+
151+
152+
def plot_linearmap(cdict):
153+
newcmp = LinearSegmentedColormap('testCmap', segmentdata=cdict, N=256)
154+
rgba = newcmp(np.linspace(0, 1, 256))
155+
fig, ax = plt.subplots(figsize=(4, 3), constrained_layout=True)
156+
col = ['r', 'g', 'b']
157+
for xx in [0.25, 0.5, 0.75]:
158+
ax.axvline(xx, color='0.7', linestyle='--')
159+
for i in range(3):
160+
ax.plot(np.arange(256)/256, rgba[:, i], color=col[i])
161+
ax.set_xlabel('index')
162+
ax.set_ylabel('RGB')
163+
plt.show()
164+
165+
plot_linearmap(cdict)
166+
167+
#############################################################################
168+
# In order to make a discontinuity at an anchor point, the third column is
169+
# different than the second. The matrix for each of "red", "green", "blue",
170+
# and optionally "alpha" is set up as::
171+
#
172+
# cdict['red'] = [...
173+
# [x[i] yleft[i] yright[i]],
174+
# [x[i+1] yleft[i+1] yright[i+1]],
175+
# ...]
176+
#
177+
# and for values passed to the colormap between ``x[i]`` and ``x[i+1]``,
178+
# the interpolation is between ``yright[i]`` and ``yleft[i+1]``.
179+
#
180+
# In the example below there is a discontiuity in red at 0.5. The
181+
# interpolation between 0 and 0.5 goes from 0.3 to 1, and between 0.5 and 1
182+
# it goes from 0.9 to 1. Note that red[0, 1], and red[2, 2] are both
183+
# superfluous to the interpolation because red[0, 1] is the value to the
184+
# left of 0, and red[2, 2] is the value to the right of 1.0.
185+
186+
cdict['red'] = [[0.0, 0.0, 0.3],
187+
[0.5, 1.0, 0.9],
188+
[1.0, 1.0, 1.0]]
189+
plot_linearmap(cdict)
190+
191+
192+
#############################################################################
193+
#
194+
# ------------
195+
#
196+
# References
197+
# """"""""""
198+
#
199+
# The use of the following functions, methods, classes and modules is shown
200+
# in this example:
201+
202+
import matplotlib
203+
matplotlib.axes.Axes.pcolormesh
204+
matplotlib.figure.Figure.colorbar
205+
matplotlib.colors
206+
matplotlib.colors.LinearSegmentedColormap
207+
matplotlib.colors.ListedColormap
208+
matplotlib.cm
209+
matplotlib.cm.get_cmap

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.