@@ -37,103 +37,101 @@ Color Conversion tools
37
37
38
38
.. _norms_and_colormaps :
39
39
40
- Normalization and Colormapping
41
- ------------------------------
40
+ Normalization and Colormapping of Continuous Data
41
+ -------------------------------------------------
42
42
43
43
Some `~.artist.Artist ` classes can map an array of input data to RGBA
44
44
values, (ex `~.axes.Axes.scatter ` or `~.axes.Axes.imshow `). The
45
45
machinery for this is implemented via the `~.cm.ScalarMappable ` base
46
46
class in `~.cm ` and the `~.Normalize ` and `~.Colormap ` classes in
47
47
`~.colors ` (this module).
48
48
49
- At the core, colormapping is going from a scalar value to a RGB tuple
50
- (formally:math: `f(x) : ℝ^1 \rightarrow ℝ^3 `). To effectively
51
- communicate through the color we want pick a:ref: `colormap suited to
52
- the data <sphx_glr_tutorials_colors_colormaps.py>` but in general
53
- "good" colormaps smoothly and continuously change their RGB values as
54
- a function of the input data. By looking at the RGB values as we go
55
- through the full range of the user data we can trace out the
56
- 1-dimensional path the colormap takes through 3-dimensional RGB space.
57
- This allows us to separate the mapping process into two orthogonal
58
- parts :
59
-
60
- 1. the parameterized path through color space
61
- 2. the mapping between the user's data to distance along the curve.
62
-
63
- The first step is expressed in Matplotlib via the `.Colormap ` family
64
- of classes and the second step is expressed through the `.Normalize ` family
65
- of classes. This allows us to fully independently pick what colors to use (by
66
- selecting the colormap), what data range to show (via the ``vmin `` and ``vmax ``
67
- attributes on `.Normalize `, or via the `.cm.ScalarMappable.set_clim ` method), and
68
- the functional transform (e.g., linear vs log) from data space to distance along the
69
- curve space.
70
-
71
- In addition to the colors in the map, `.Colormap ` objects carry three
72
- additional colors:
73
-
74
- - over (`.Colormap.set_over ` / `.Colormap.get_over `)
75
- - under (`.Colormap.set_under ` / `.Colormap.get_under `)
76
- - bad (`.Colormap.set_bad ` / `.Colormap.get_bad `)
77
-
78
- The first two (over / under) control what should be done for values
79
- that are greater or less than the data range set by the user. By
80
- default these are equal to the top and bottom colors of the color map.
81
- The "bad" value is used for masked or non-finite values (e.g. nan and
82
- inf) and defaults to transparent.
83
-
84
-
85
- ..note ::
49
+ At the core, colormapping is going from a scalar value to a RGB tuple (formally
50
+ :math: `f(x) : ℝ^1 \rightarrow ℝ^3 `). To effectively communicate through the
51
+ color we want pick a:ref: `colormap suited to the data
52
+ <sphx_glr_tutorials_colors_colormaps.py>`. For continuous data types [#f1 ]_ a
53
+ "good" colormap smoothly and continuously change their RGB values as a function
54
+ of the input that trace out a 1-dimensional path through the 3-dimensional RGB
55
+ space [#f2 ]_. We can restrict the domain of:math: `f` to $[0, 1]$ which we
56
+ interpret as the normalized distance along the curve. This allows us to
57
+ cleanly separate the mapping process from the continuous input data to RGB into
58
+ two steps:
59
+
60
+ 1. the mapping between the user's data to distance along the curve
61
+ 2. the parameterized path through color space.
62
+
63
+ The first step is expressed through the `.Normalize ` family of classes and the
64
+ second is expressed in Matplotlib via the `.Colormap ` family of classes. This
65
+ allows us to fully independently pick the functional transform (e.g., linear vs
66
+ log) from data space to distance along the curve space, what (user) data range
67
+ to show (via the ``vmin `` and ``vmax `` attributes on `.Normalize `, or via the
68
+ `.cm.ScalarMappable.set_clim ` method), and what colors to use (by selecting the
69
+ `.Colormap `). Both `.Colormap ` and `.Normalize ` are implemented as `callable
70
+ classes <https://docs.python.org/3/reference/datamodel.html#object.__call__> `__
71
+ which allows use to bind some (mutable) state to a function call. The complete
72
+ functionality is exposed in the `.ScalarMappable ` family of artists which have
73
+ a `.Colormap ` and `.Normalize ` instances and are responsible for invoking them
74
+ at draw time.
75
+
76
+ The `.Normalize ` family has 3 common attributes: *vmin *, *vmax *, and *clip *
77
+ which control the data limits. The `.Normalize.__call__ ` signature is ::
78
+
79
+ def __call__(value: RawData, clip:Optional[Bool] =None) -> NormedData:
80
+ ...
86
81
87
- Using `.cm.get_cmap ` may return to you a reference to a globally
88
- visible instance of the colormap (rather than a new instance). If
89
- you plan to set the over/under/bad values we recommend you first
90
- make a copy ::
82
+ It takes in data in the user's data space and converts it to *NormedData * with
83
+ the range:
91
84
92
- from copy import copy
93
- import matplotlib.cm as mcm
85
+ ..math ::
94
86
95
- my_cmap = copy(mcm.get_cmap('viridis'))
87
+ \begin {cases}
88
+ \mathrm {under} & d < vmin \\
89
+ [0 ,1 ] & vmin\leq d\leq vmax \\
90
+ \mathrm {over} & vmax < d \\
91
+ \mathrm {bad} & !\mathrm {np.finite(d)}
92
+ \end {cases}
96
93
97
94
98
- Both `.Colormap ` and `.Normalize ` are implemented as `callable classes
99
- <https://docs.python.org/3/reference/datamodel.html#object.__call__> `__ which
100
- allows use to bind some (mutable) state to a function call.
101
95
102
- The `.Normalize.__call__ ` signature is ::
96
+ The `.Colormap.__call__ ` signature when passed *NormedData * (floats) [#f3 ]_ is
97
+ ::
103
98
104
- def normalize(value: RawData, clip:Optional[Bool] =None):
99
+ def __call__(self, X: NormedData,
100
+ alpha:Optional[float] =None, bytes:Bool=False) -> RGBA:
105
101
...
106
102
107
- It takes in data in the user's data space and converts it to *NormedData *. The
108
- *clip * parameter allows you to override the value set at class instantiation time
109
- and controls if the input data is clipped to the range:math: `[vmin, vmax]` before
110
- being transformed or not.
111
-
112
- The `.Colormap.__call__ ` signature when passed floats ::
113
-
114
- def map(X: NormedData, alpha:Optional[float] =None, bytes:Bool=False) -> RGBA:
115
- ...
103
+ In addition to parameterized path through RGB (which handles values in $[0,
104
+ 1]$, `.Colormap ` objects carry three additional colors:
116
105
117
- It takes data in a "normalized" space and:
106
+ - *over * (`.Colormap.set_over ` / `.Colormap.get_over `)
107
+ - *under * (`.Colormap.set_under ` / `.Colormap.get_under `)
108
+ - *bad * (`.Colormap.set_bad ` / `.Colormap.get_bad `)
118
109
119
- - maps values in the closed set ``[0, 1] `` to that fraction along the curve
120
- - maps any value greater than 1 to the "over" color
121
- - maps any value less than 0 to the "under" color
122
- - maps any non-finite or masked value to the "bad" color
110
+ which control the color for the corresponding values in *NormedData *.
111
+ By default the over and under colors are the top and bottom colors of
112
+ the colormap respectively and bad is transparent.
123
113
124
- broadcasting to match the input shape (scalar to tuple, n-D array to
125
- (n+1)-D array).
114
+ ..warning ::
126
115
127
- .. note ::
128
-
129
- This can be useful to draw a set of colors from a colormap ::
116
+ Using `.cm.get_cmap ` may return to you a reference to a globally
117
+ visible instance of the colormap (rather than a new instance). If
118
+ you plan to set the over/under/bad values we recommend you first
119
+ make a copy ::
130
120
121
+ from copy import copy
131
122
import matplotlib.cm as mcm
132
- import numpy as np
133
123
134
- cmap = mcm.get_cmap('viridis')
135
- array_of_colors = cmap(np.arange(0, 1, 5))
124
+ my_cmap = copy(mcm.get_cmap('viridis'))
136
125
126
+ ..rubric ::Footnotes
127
+
128
+ .. [#f1 ]Discrete data types, such as Categorical and Ordinal, have different
129
+ considerations.
130
+ .. [#f2 ]Notable, the cubehelix colormap is named because it traces a helix
131
+ through the RGB color cube from black to white.
132
+ .. [#f3 ]Discrete data, as handled by `.NoNorm ` and `.BoundaryNorm ` are passed
133
+ as integers and act as direct Look Up Table (LUT) indexes into the
134
+ colormap.
137
135
138
136
In practice
139
137
~~~~~~~~~~~
@@ -237,10 +235,30 @@ see them pulled out:
237
235
[1., 0., 0., 1.]])
238
236
239
237
238
+
239
+ Directly using a `.Colormap ` outside of a `.ScalarMappable ` can be useful
240
+ to generate a family of coherent colors for plotting
241
+
242
+ ..plot ::
243
+ :include-source:
244
+
245
+ import matplotlib.cm as mcm
246
+ import numpy as np
247
+
248
+ cmap = mcm.get_cmap('viridis')
249
+ array_of_colors = cmap(np.linspace(0, 1, 5))
250
+
251
+ x = np.linspace(0, 1, 25)
252
+ fig, ax = plt.subplots(constrained_layout=True)
253
+ for j, color in enumerate(array_of_colors):
254
+ ax.plot(x, x**j, color=color, label=f'$x^{j}$')
255
+ ax.legend()
256
+
240
257
API
241
258
~~~
242
259
243
-
260
+ Colormap Classes
261
+ ++++++++++++++++
244
262
245
263
..autosummary ::
246
264
:toctree: _as_gen/
@@ -251,18 +269,37 @@ API
251
269
ListedColormap
252
270
253
271
272
+ ..inheritance-diagram ::matplotlib.colors.Colormap matplotlib.colors.LinearSegmentedColormap matplotlib.colors.ListedColormap
273
+ :parts: 1
274
+ :private-bases:
275
+
276
+
277
+ Norm Classes
278
+ ++++++++++++
279
+
254
280
..autosummary ::
255
281
:toctree: _as_gen/
256
282
:template: autosummary.rst
257
283
258
284
Normalize
259
285
LogNorm
260
286
CenteredNorm
261
- BoundaryNorm
262
287
TwoSlopeNorm
263
288
PowerNorm
264
- NoNorm
265
289
SymLogNorm
290
+ FuncNorm
291
+ BoundaryNorm
292
+ NoNorm
293
+
294
+
295
+ ..inheritance-diagram ::matplotlib.colors.Normalize matplotlib.colors.LogNorm matplotlib.colors.PowerNorm matplotlib.colors.NoNorm matplotlib.colors.TwoSlopeNorm matplotlib.colors.SymLogNorm matplotlib.colors.BoundaryNorm matplotlib.colors.FuncNorm matplotlib.colors.CenteredNorm
296
+ :parts: 1
297
+ :private-bases:
298
+
299
+
300
+ Factory Functions & Decorators
301
+ ++++++++++++++++++++++++++++++
302
+
266
303
267
304
..autosummary ::
268
305
:toctree: _as_gen/
272
309
make_norm_from_scale
273
310
274
311
275
- ..inheritance-diagram ::matplotlib.colors.Colormap matplotlib.colors.LinearSegmentedColormap matplotlib.colors.ListedColormap
276
- :parts: 1
277
- :private-bases:
278
-
279
-
280
- ..inheritance-diagram ::matplotlib.colors.Normalize matplotlib.colors.LogNorm matplotlib.colors.PowerNorm matplotlib.colors.NoNorm matplotlib.colors.TwoSlopeNorm matplotlib.colors.SymLogNorm matplotlib.colors.BoundaryNorm
281
- :parts: 1
282
- :private-bases:
283
-
284
312
285
313
Hill Shading
286
314
------------