matplotlib & pandas

This commit is contained in:
estomm
2020-09-26 22:03:11 +08:00
parent 73cc328c81
commit d31be4f219
599 changed files with 99925 additions and 0 deletions

View File

@@ -0,0 +1,123 @@
---
sidebarDepth: 3
sidebar: auto
---
# Customized Colorbars Tutorial
This tutorial shows how to build colorbars without an attached plot.
## Customized Colorbars
[``ColorbarBase``](https://matplotlib.orgapi/colorbar_api.html#matplotlib.colorbar.ColorbarBase) puts a colorbar in a specified axes,
and can make a colorbar for a given colormap; it does not need a mappable
object like an image. In this tutorial we will explore what can be done with
standalone colorbar.
### Basic continuous colorbar
Set the colormap and norm to correspond to the data for which the colorbar
will be used. Then create the colorbar by calling
[``ColorbarBase``](https://matplotlib.orgapi/colorbar_api.html#matplotlib.colorbar.ColorbarBase) and specify axis, colormap, norm
and orientation as parameters. Here we create a basic continuous colorbar
with ticks and labels. For more information see the
[``colorbar``](https://matplotlib.orgapi/colorbar_api.html#module-matplotlib.colorbar) API.
``` python
import matplotlib.pyplot as plt
import matplotlib as mpl
fig, ax = plt.subplots(figsize=(6, 1))
fig.subplots_adjust(bottom=0.5)
cmap = mpl.cm.cool
norm = mpl.colors.Normalize(vmin=5, vmax=10)
cb1 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
orientation='horizontal')
cb1.set_label('Some Units')
fig.show()
```
![sphx_glr_colorbar_only_001](https://matplotlib.org/_images/sphx_glr_colorbar_only_001.png)
### Discrete intervals colorbar
The second example illustrates the use of a
[``ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap) which generates a colormap from a
set of listed colors, ``colors.BoundaryNorm()`` which generates a colormap
index based on discrete intervals and extended ends to show the "over" and
"under" value colors. Over and under are used to display data outside of the
normalized [0,1] range. Here we pass colors as gray shades as a string
encoding a float in the 0-1 range.
If a [``ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap) is used, the length of the
bounds array must be one greater than the length of the color list. The
bounds must be monotonically increasing.
This time we pass some more arguments in addition to previous arguments to
[``ColorbarBase``](https://matplotlib.orgapi/colorbar_api.html#matplotlib.colorbar.ColorbarBase). For the out-of-range values to
display on the colorbar, we have to use the *extend* keyword argument. To use
*extend*, you must specify two extra boundaries. Finally spacing argument
ensures that intervals are shown on colorbar proportionally.
``` python
fig, ax = plt.subplots(figsize=(6, 1))
fig.subplots_adjust(bottom=0.5)
cmap = mpl.colors.ListedColormap(['red', 'green', 'blue', 'cyan'])
cmap.set_over('0.25')
cmap.set_under('0.75')
bounds = [1, 2, 4, 7, 8]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
cb2 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
boundaries=[0] + bounds + [13],
extend='both',
ticks=bounds,
spacing='proportional',
orientation='horizontal')
cb2.set_label('Discrete intervals, some other units')
fig.show()
```
![sphx_glr_colorbar_only_002](https://matplotlib.org/_images/sphx_glr_colorbar_only_002.png)
### Colorbar with custom extension lengths
Here we illustrate the use of custom length colorbar extensions, used on a
colorbar with discrete intervals. To make the length of each extension the
same as the length of the interior colors, use ``extendfrac='auto'``.
``` python
fig, ax = plt.subplots(figsize=(6, 1))
fig.subplots_adjust(bottom=0.5)
cmap = mpl.colors.ListedColormap(['royalblue', 'cyan',
'yellow', 'orange'])
cmap.set_over('red')
cmap.set_under('blue')
bounds = [-1.0, -0.5, 0.0, 0.5, 1.0]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
cb3 = mpl.colorbar.ColorbarBase(ax, cmap=cmap,
norm=norm,
boundaries=[-10] + bounds + [10],
extend='both',
extendfrac='auto',
ticks=bounds,
spacing='uniform',
orientation='horizontal')
cb3.set_label('Custom extension lengths, some other units')
fig.show()
```
![sphx_glr_colorbar_only_003](https://matplotlib.org/_images/sphx_glr_colorbar_only_003.png)
## Download
- [Download Python source code: colorbar_only.py](https://matplotlib.org/_downloads/23690f47313380b801750e3adc4c317e/colorbar_only.py)
- [Download Jupyter notebook: colorbar_only.ipynb](https://matplotlib.org/_downloads/4d3eb6ad2b03a5eb988f576ea050f104/colorbar_only.ipynb)

View File

@@ -0,0 +1,311 @@
---
sidebarDepth: 3
sidebar: auto
---
# Creating Colormaps in Matplotlib
Matplotlib has a number of built-in colormaps accessible via
[``matplotlib.cm.get_cmap``](https://matplotlib.orgapi/cm_api.html#matplotlib.cm.get_cmap). There are also external libraries like
[palettable](https://jiffyclub.github.io/palettable/) that have many extra colormaps.
However, we often want to create or manipulate colormaps in Matplotlib.
This can be done using the class [``ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap) and a Nx4 numpy array of
values between 0 and 1 to represent the RGBA values of the colormap. There
is also a [``LinearSegmentedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.LinearSegmentedColormap.html#matplotlib.colors.LinearSegmentedColormap) class that allows colormaps to be
specified with a few anchor points defining segments, and linearly
interpolating between the anchor points.
## Getting colormaps and accessing their values
First, getting a named colormap, most of which are listed in
[Choosing Colormaps in Matplotlib](colormaps.html) requires the use of
[``matplotlib.cm.get_cmap``](https://matplotlib.orgapi/cm_api.html#matplotlib.cm.get_cmap), which returns a
[``matplotlib.colors.ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap) object. The second argument gives
the size of the list of colors used to define the colormap, and below we
use a modest value of 12 so there are not a lot of values to look at.
``` python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
viridis = cm.get_cmap('viridis', 12)
print(viridis)
```
Out:
```
<matplotlib.colors.ListedColormap object at 0x7f7f3c724390>
```
The object ``viridis`` is a callable, that when passed a float between
0 and 1 returns an RGBA value from the colormap:
``` python
print(viridis(0.56))
```
Out:
```
(0.119512, 0.607464, 0.540218, 1.0)
```
The list of colors that comprise the colormap can be directly accessed using
the ``colors`` property,
or it can be accessed indirectly by calling ``viridis`` with an array
of values matching the length of the colormap. Note that the returned list
is in the form of an RGBA Nx4 array, where N is the length of the colormap.
``` python
print('viridis.colors', viridis.colors)
print('viridis(range(12))', viridis(range(12)))
print('viridis(np.linspace(0, 1, 12))', viridis(np.linspace(0, 1, 12)))
```
Out:
```
viridis.colors [[0.267004 0.004874 0.329415 1. ]
[0.283072 0.130895 0.449241 1. ]
[0.262138 0.242286 0.520837 1. ]
[0.220057 0.343307 0.549413 1. ]
[0.177423 0.437527 0.557565 1. ]
[0.143343 0.522773 0.556295 1. ]
[0.119512 0.607464 0.540218 1. ]
[0.166383 0.690856 0.496502 1. ]
[0.319809 0.770914 0.411152 1. ]
[0.525776 0.833491 0.288127 1. ]
[0.762373 0.876424 0.137064 1. ]
[0.993248 0.906157 0.143936 1. ]]
viridis(range(12)) [[0.267004 0.004874 0.329415 1. ]
[0.283072 0.130895 0.449241 1. ]
[0.262138 0.242286 0.520837 1. ]
[0.220057 0.343307 0.549413 1. ]
[0.177423 0.437527 0.557565 1. ]
[0.143343 0.522773 0.556295 1. ]
[0.119512 0.607464 0.540218 1. ]
[0.166383 0.690856 0.496502 1. ]
[0.319809 0.770914 0.411152 1. ]
[0.525776 0.833491 0.288127 1. ]
[0.762373 0.876424 0.137064 1. ]
[0.993248 0.906157 0.143936 1. ]]
viridis(np.linspace(0, 1, 12)) [[0.267004 0.004874 0.329415 1. ]
[0.283072 0.130895 0.449241 1. ]
[0.262138 0.242286 0.520837 1. ]
[0.220057 0.343307 0.549413 1. ]
[0.177423 0.437527 0.557565 1. ]
[0.143343 0.522773 0.556295 1. ]
[0.119512 0.607464 0.540218 1. ]
[0.166383 0.690856 0.496502 1. ]
[0.319809 0.770914 0.411152 1. ]
[0.525776 0.833491 0.288127 1. ]
[0.762373 0.876424 0.137064 1. ]
[0.993248 0.906157 0.143936 1. ]]
```
The colormap is a lookup table, so "oversampling" the colormap returns
nearest-neighbor interpolation (note the repeated colors in the list below)
``` python
print('viridis(np.linspace(0, 1, 15))', viridis(np.linspace(0, 1, 15)))
```
Out:
```
viridis(np.linspace(0, 1, 15)) [[0.267004 0.004874 0.329415 1. ]
[0.267004 0.004874 0.329415 1. ]
[0.283072 0.130895 0.449241 1. ]
[0.262138 0.242286 0.520837 1. ]
[0.220057 0.343307 0.549413 1. ]
[0.177423 0.437527 0.557565 1. ]
[0.143343 0.522773 0.556295 1. ]
[0.119512 0.607464 0.540218 1. ]
[0.119512 0.607464 0.540218 1. ]
[0.166383 0.690856 0.496502 1. ]
[0.319809 0.770914 0.411152 1. ]
[0.525776 0.833491 0.288127 1. ]
[0.762373 0.876424 0.137064 1. ]
[0.993248 0.906157 0.143936 1. ]
[0.993248 0.906157 0.143936 1. ]]
```
## Creating listed colormaps
This is essential the inverse operation of the above where we supply a
Nx4 numpy array with all values between 0 and 1,
to [``ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap) to make a new colormap. This means that
any numpy operations that we can do on a Nx4 array make carpentry of
new colormaps from existing colormaps quite straight forward.
Suppose we want to make the first 25 entries of a 256-length "viridis"
colormap pink for some reason:
``` python
viridis = cm.get_cmap('viridis', 256)
newcolors = viridis(np.linspace(0, 1, 256))
pink = np.array([248/256, 24/256, 148/256, 1])
newcolors[:25, :] = pink
newcmp = ListedColormap(newcolors)
def plot_examples(cms):
"""
helper function to plot two colormaps
"""
np.random.seed(19680801)
data = np.random.randn(30, 30)
fig, axs = plt.subplots(1, 2, figsize=(6, 3), constrained_layout=True)
for [ax, cmap] in zip(axs, cms):
psm = ax.pcolormesh(data, cmap=cmap, rasterized=True, vmin=-4, vmax=4)
fig.colorbar(psm, ax=ax)
plt.show()
plot_examples([viridis, newcmp])
```
![sphx_glr_colormap-manipulation_001](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_001.png)
We can easily reduce the dynamic range of a colormap; here we choose the
middle 0.5 of the colormap. However, we need to interpolate from a larger
colormap, otherwise the new colormap will have repeated values.
``` python
viridisBig = cm.get_cmap('viridis', 512)
newcmp = ListedColormap(viridisBig(np.linspace(0.25, 0.75, 256)))
plot_examples([viridis, newcmp])
```
![sphx_glr_colormap-manipulation_002](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_002.png)
and we can easily concatenate two colormaps:
``` python
top = cm.get_cmap('Oranges_r', 128)
bottom = cm.get_cmap('Blues', 128)
newcolors = np.vstack((top(np.linspace(0, 1, 128)),
bottom(np.linspace(0, 1, 128))))
newcmp = ListedColormap(newcolors, name='OrangeBlue')
plot_examples([viridis, newcmp])
```
![sphx_glr_colormap-manipulation_003](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_003.png)
Of course we need not start from a named colormap, we just need to create
the Nx4 array to pass to [``ListedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.ListedColormap.html#matplotlib.colors.ListedColormap). Here we create a
brown colormap that goes to white....
``` python
N = 256
vals = np.ones((N, 4))
vals[:, 0] = np.linspace(90/256, 1, N)
vals[:, 1] = np.linspace(39/256, 1, N)
vals[:, 2] = np.linspace(41/256, 1, N)
newcmp = ListedColormap(vals)
plot_examples([viridis, newcmp])
```
![sphx_glr_colormap-manipulation_004](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_004.png)
## Creating linear segmented colormaps
[``LinearSegmentedColormap``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.LinearSegmentedColormap.html#matplotlib.colors.LinearSegmentedColormap) class specifies colormaps using anchor points
between which RGB(A) values are interpolated.
The format to specify these colormaps allows discontinuities at the anchor
points. Each anchor point is specified as a row in a matrix of the
form ``[x[i] yleft[i] yright[i]]``, where ``x[i]`` is the anchor, and
``yleft[i]`` and ``yright[i]`` are the values of the color on either
side of the anchor point.
If there are no discontinuities, then ``yleft[i]=yright[i]``:
``` python
cdict = {'red': [[0.0, 0.0, 0.0],
[0.5, 1.0, 1.0],
[1.0, 1.0, 1.0]],
'green': [[0.0, 0.0, 0.0],
[0.25, 0.0, 0.0],
[0.75, 1.0, 1.0],
[1.0, 1.0, 1.0]],
'blue': [[0.0, 0.0, 0.0],
[0.5, 0.0, 0.0],
[1.0, 1.0, 1.0]]}
def plot_linearmap(cdict):
newcmp = LinearSegmentedColormap('testCmap', segmentdata=cdict, N=256)
rgba = newcmp(np.linspace(0, 1, 256))
fig, ax = plt.subplots(figsize=(4, 3), constrained_layout=True)
col = ['r', 'g', 'b']
for xx in [0.25, 0.5, 0.75]:
ax.axvline(xx, color='0.7', linestyle='--')
for i in range(3):
ax.plot(np.arange(256)/256, rgba[:, i], color=col[i])
ax.set_xlabel('index')
ax.set_ylabel('RGB')
plt.show()
plot_linearmap(cdict)
```
![sphx_glr_colormap-manipulation_005](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_005.png)
In order to make a discontinuity at an anchor point, the third column is
different than the second. The matrix for each of "red", "green", "blue",
and optionally "alpha" is set up as:
``` python
cdict['red'] = [...
[x[i] yleft[i] yright[i]],
[x[i+1] yleft[i+1] yright[i+1]],
...]
```
and for values passed to the colormap between ``x[i]`` and ``x[i+1]``,
the interpolation is between ``yright[i]`` and ``yleft[i+1]``.
In the example below there is a discontinuity in red at 0.5. The
interpolation between 0 and 0.5 goes from 0.3 to 1, and between 0.5 and 1
it goes from 0.9 to 1. Note that red[0, 1], and red[2, 2] are both
superfluous to the interpolation because red[0, 1] is the value to the
left of 0, and red[2, 2] is the value to the right of 1.0.
``` python
cdict['red'] = [[0.0, 0.0, 0.3],
[0.5, 1.0, 0.9],
[1.0, 1.0, 1.0]]
plot_linearmap(cdict)
```
![sphx_glr_colormap-manipulation_006](https://matplotlib.org/_images/sphx_glr_colormap-manipulation_006.png)
### References
The use of the following functions, methods, classes and modules is shown
in this example:
``` python
import matplotlib
matplotlib.axes.Axes.pcolormesh
matplotlib.figure.Figure.colorbar
matplotlib.colors
matplotlib.colors.LinearSegmentedColormap
matplotlib.colors.ListedColormap
matplotlib.cm
matplotlib.cm.get_cmap
```
**Total running time of the script:** ( 0 minutes 2.220 seconds)
## Download
- [Download Python source code: colormap-manipulation.py](https://matplotlib.org/_downloads/f55e73a6ac8441fd68270d3c6f2a7c7c/colormap-manipulation.py)
- [Download Jupyter notebook: colormap-manipulation.ipynb](https://matplotlib.org/_downloads/fd9acfdbb45f341d3bb04199f0868a38/colormap-manipulation.ipynb)

View File

@@ -0,0 +1,281 @@
---
sidebarDepth: 3
sidebar: auto
---
# Colormap Normalization
Objects that use colormaps by default linearly map the colors in the
colormap from data values *vmin* to *vmax*. For example:
``` python
pcm = ax.pcolormesh(x, y, Z, vmin=-1., vmax=1., cmap='RdBu_r')
```
will map the data in *Z* linearly from -1 to +1, so *Z=0* will
give a color at the center of the colormap *RdBu_r* (white in this
case).
Matplotlib does this mapping in two steps, with a normalization from
the input data to [0, 1] occurring first, and then mapping onto the
indices in the colormap. Normalizations are classes defined in the
[``matplotlib.colors()``](https://matplotlib.orgapi/colors_api.html#module-matplotlib.colors) module. The default, linear normalization
is [``matplotlib.colors.Normalize()``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.Normalize.html#matplotlib.colors.Normalize).
Artists that map data to color pass the arguments *vmin* and *vmax* to
construct a [``matplotlib.colors.Normalize()``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.Normalize.html#matplotlib.colors.Normalize) instance, then call it:
``` python
In [1]: import matplotlib as mpl
In [2]: norm = mpl.colors.Normalize(vmin=-1.,vmax=1.)
In [3]: norm(0.)
Out[3]: 0.5
```
However, there are sometimes cases where it is useful to map data to
colormaps in a non-linear fashion.
## Logarithmic
One of the most common transformations is to plot data by taking its logarithm
(to the base-10). This transformation is useful to display changes across
disparate scales. Using [``colors.LogNorm``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.LogNorm.html#matplotlib.colors.LogNorm) normalizes the data via
\(log_{10}\). In the example below, there are two bumps, one much smaller
than the other. Using [``colors.LogNorm``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.LogNorm.html#matplotlib.colors.LogNorm), the shape and location of each bump
can clearly be seen:
``` python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cbook as cbook
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
# A low hump with a spike coming out of the top right. Needs to have
# z/colour axis on a log scale so we see both hump and spike. linear
# scale only shows the spike.
Z1 = np.exp(-(X)**2 - (Y)**2)
Z2 = np.exp(-(X * 10)**2 - (Y * 10)**2)
Z = Z1 + 50 * Z2
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolor(X, Y, Z,
norm=colors.LogNorm(vmin=Z.min(), vmax=Z.max()),
cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')
pcm = ax[1].pcolor(X, Y, Z, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
plt.show()
```
![sphx_glr_colormapnorms_001](https://matplotlib.org/_images/sphx_glr_colormapnorms_001.png)
## Symmetric logarithmic
Similarly, it sometimes happens that there is data that is positive
and negative, but we would still like a logarithmic scaling applied to
both. In this case, the negative numbers are also scaled
logarithmically, and mapped to smaller numbers; e.g., if ``vmin=-vmax``,
then they the negative numbers are mapped from 0 to 0.5 and the
positive from 0.5 to 1.
Since the logarithm of values close to zero tends toward infinity, a
small range around zero needs to be mapped linearly. The parameter
*linthresh* allows the user to specify the size of this range
(-*linthresh*, *linthresh*). The size of this range in the colormap is
set by *linscale*. When *linscale* == 1.0 (the default), the space used
for the positive and negative halves of the linear range will be equal
to one decade in the logarithmic range.
``` python
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z,
norm=colors.SymLogNorm(linthresh=0.03, linscale=0.03,
vmin=-1.0, vmax=1.0),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')
pcm = ax[1].pcolormesh(X, Y, Z, cmap='RdBu_r', vmin=-np.max(Z))
fig.colorbar(pcm, ax=ax[1], extend='both')
plt.show()
```
![sphx_glr_colormapnorms_002](https://matplotlib.org/_images/sphx_glr_colormapnorms_002.png)
## Power-law
Sometimes it is useful to remap the colors onto a power-law
relationship (i.e. \(y=x^{\gamma}\), where \(\gamma\) is the
power). For this we use the ``colors.PowerNorm()``. It takes as an
argument *gamma* (*gamma* == 1.0 will just yield the default linear
normalization):
::: tip Note
There should probably be a good reason for plotting the data using
this type of transformation. Technical viewers are used to linear
and logarithmic axes and data transformations. Power laws are less
common, and viewers should explicitly be made aware that they have
been used.
:::
``` python
N = 100
X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
Z1 = (1 + np.sin(Y * 10.)) * X**(2.)
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1, norm=colors.PowerNorm(gamma=0.5),
cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
plt.show()
```
![sphx_glr_colormapnorms_003](https://matplotlib.org/_images/sphx_glr_colormapnorms_003.png)
## Discrete bounds
Another normaization that comes with Matplotlib is
``colors.BoundaryNorm()``. In addition to *vmin* and *vmax*, this
takes as arguments boundaries between which data is to be mapped. The
colors are then linearly distributed between these "bounds". For
instance:
``` python
In [4]: import matplotlib.colors as colors
In [5]: bounds = np.array([-0.25, -0.125, 0, 0.5, 1])
In [6]: norm = colors.BoundaryNorm(boundaries=bounds, ncolors=4)
In [7]: print(norm([-0.2,-0.15,-0.02, 0.3, 0.8, 0.99]))
[0 0 1 2 3 3]
```
Note unlike the other norms, this norm returns values from 0 to *ncolors*-1.
``` python
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
Z = (Z1 - Z2) * 2
fig, ax = plt.subplots(3, 1, figsize=(8, 8))
ax = ax.flatten()
# even bounds gives a contour-like effect
bounds = np.linspace(-1, 1, 10)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[0].pcolormesh(X, Y, Z,
norm=norm,
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical')
# uneven bounds changes the colormapping:
bounds = np.array([-0.25, -0.125, 0, 0.5, 1])
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[1].pcolormesh(X, Y, Z, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
pcm = ax[2].pcolormesh(X, Y, Z, cmap='RdBu_r', vmin=-np.max(Z))
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
plt.show()
```
![sphx_glr_colormapnorms_004](https://matplotlib.org/_images/sphx_glr_colormapnorms_004.png)
## DivergingNorm: Different mapping on either side of a center
Sometimes we want to have a different colormap on either side of a
conceptual center point, and we want those two colormaps to have
different linear scales. An example is a topographic map where the land
and ocean have a center at zero, but land typically has a greater
elevation range than the water has depth range, and they are often
represented by a different colormap.
``` python
filename = cbook.get_sample_data('topobathy.npz', asfileobj=False)
with np.load(filename) as dem:
topo = dem['topo']
longitude = dem['longitude']
latitude = dem['latitude']
fig, ax = plt.subplots()
# make a colormap that has land and ocean clearly delineated and of the
# same length (256 + 256)
colors_undersea = plt.cm.terrain(np.linspace(0, 0.17, 256))
colors_land = plt.cm.terrain(np.linspace(0.25, 1, 256))
all_colors = np.vstack((colors_undersea, colors_land))
terrain_map = colors.LinearSegmentedColormap.from_list('terrain_map',
all_colors)
# make the norm: Note the center is offset so that the land has more
# dynamic range:
divnorm = colors.DivergingNorm(vmin=-500., vcenter=0, vmax=4000)
pcm = ax.pcolormesh(longitude, latitude, topo, rasterized=True, norm=divnorm,
cmap=terrain_map,)
# Simple geographic plot, set aspect ratio beecause distance between lines of
# longitude depends on latitude.
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
fig.colorbar(pcm, shrink=0.6)
plt.show()
```
![sphx_glr_colormapnorms_005](https://matplotlib.org/_images/sphx_glr_colormapnorms_005.png)
## Custom normalization: Manually implement two linear ranges
The [``DivergingNorm``](https://matplotlib.orgapi/_as_gen/matplotlib.colors.DivergingNorm.html#matplotlib.colors.DivergingNorm) described above makes a useful example for
defining your own norm.
``` python
class MidpointNormalize(colors.Normalize):
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
self.vcenter = vcenter
colors.Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
# I'm ignoring masked values and all kinds of edge cases to make a
# simple example...
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
fig, ax = plt.subplots()
midnorm = MidpointNormalize(vmin=-500., vcenter=0, vmax=4000)
pcm = ax.pcolormesh(longitude, latitude, topo, rasterized=True, norm=midnorm,
cmap=terrain_map)
ax.set_aspect(1 / np.cos(np.deg2rad(49)))
fig.colorbar(pcm, shrink=0.6, extend='both')
plt.show()
```
![sphx_glr_colormapnorms_006](https://matplotlib.org/_images/sphx_glr_colormapnorms_006.png)
**Total running time of the script:** ( 0 minutes 1.895 seconds)
## Download
- [Download Python source code: colormapnorms.py](https://matplotlib.org/_downloads/56fa91958fd427757e621c21de870bda/colormapnorms.py)
- [Download Jupyter notebook: colormapnorms.ipynb](https://matplotlib.org/_downloads/59a7c8f3db252ae16cd43fd50d6a004c/colormapnorms.ipynb)

View File

@@ -0,0 +1,521 @@
---
sidebarDepth: 3
sidebar: auto
---
# Choosing Colormaps in Matplotlib
Matplotlib has a number of built-in colormaps accessible via
[``matplotlib.cm.get_cmap``](https://matplotlib.orgapi/cm_api.html#matplotlib.cm.get_cmap). There are also external libraries like
[[palettable]](#palettable) and [[colorcet]](#colorcet) that have many extra colormaps.
Here we briefly discuss how to choose between the many options. For
help on creating your own colormaps, see
[Creating Colormaps in Matplotlib](colormap-manipulation.html).
## Overview
The idea behind choosing a good colormap is to find a good representation in 3D
colorspace for your data set. The best colormap for any given data set depends
on many things including:
- Whether representing form or metric data ([[Ware]](#ware))
- Your knowledge of the data set (*e.g.*, is there a critical value
from which the other values deviate?)
- If there is an intuitive color scheme for the parameter you are plotting
- If there is a standard in the field the audience may be expecting
For many applications, a perceptually uniform colormap is the best
choice --- one in which equal steps in data are perceived as equal
steps in the color space. Researchers have found that the human brain
perceives changes in the lightness parameter as changes in the data
much better than, for example, changes in hue. Therefore, colormaps
which have monotonically increasing lightness through the colormap
will be better interpreted by the viewer. A wonderful example of
perceptually uniform colormaps is [[colorcet]](#colorcet).
Color can be represented in 3D space in various ways. One way to represent color
is using CIELAB. In CIELAB, color space is represented by lightness,
\(L^*\); red-green, \(a^*\); and yellow-blue, \(b^*\). The lightness
parameter \(L^*\) can then be used to learn more about how the matplotlib
colormaps will be perceived by viewers.
An excellent starting resource for learning about human perception of colormaps
is from [[IBM]](#ibm).
## Classes of colormaps
Colormaps are often split into several categories based on their function (see,
*e.g.*, [[Moreland]](#moreland)):
1. Sequential: change in lightness and often saturation of color
incrementally, often using a single hue; should be used for
representing information that has ordering.
1. Diverging: change in lightness and possibly saturation of two
different colors that meet in the middle at an unsaturated color;
should be used when the information being plotted has a critical
middle value, such as topography or when the data deviates around
zero.
1. Cyclic: change in lightness of two different colors that meet in
the middle and beginning/end at an unsaturated color; should be
used for values that wrap around at the endpoints, such as phase
angle, wind direction, or time of day.
1. Qualitative: often are miscellaneous colors; should be used to
represent information which does not have ordering or
relationships.
``` python
# sphinx_gallery_thumbnail_number = 2
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm
from colorspacious import cspace_converter
from collections import OrderedDict
cmaps = OrderedDict()
```
### Sequential
For the Sequential plots, the lightness value increases monotonically through
the colormaps. This is good. Some of the \(L^*\) values in the colormaps
span from 0 to 100 (binary and the other grayscale), and others start around
\(L^*=20\). Those that have a smaller range of \(L^*\) will accordingly
have a smaller perceptual range. Note also that the \(L^*\) function varies
amongst the colormaps: some are approximately linear in \(L^*\) and others
are more curved.
``` python
cmaps['Perceptually Uniform Sequential'] = [
'viridis', 'plasma', 'inferno', 'magma', 'cividis']
cmaps['Sequential'] = [
'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds',
'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu',
'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']
```
### Sequential2
Many of the \(L^*\) values from the Sequential2 plots are monotonically
increasing, but some (autumn, cool, spring, and winter) plateau or even go both
up and down in \(L^*\) space. Others (afmhot, copper, gist_heat, and hot)
have kinks in the \(L^*\) functions. Data that is being represented in a
region of the colormap that is at a plateau or kink will lead to a perception of
banding of the data in those values in the colormap (see [[mycarta-banding]](#mycarta-banding) for
an excellent example of this).
``` python
cmaps['Sequential (2)'] = [
'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia',
'hot', 'afmhot', 'gist_heat', 'copper']
```
### Diverging
For the Diverging maps, we want to have monotonically increasing \(L^*\)
values up to a maximum, which should be close to \(L^*=100\), followed by
monotonically decreasing \(L^*\) values. We are looking for approximately
equal minimum \(L^*\) values at opposite ends of the colormap. By these
measures, BrBG and RdBu are good options. coolwarm is a good option, but it
doesn't span a wide range of \(L^*\) values (see grayscale section below).
``` python
cmaps['Diverging'] = [
'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu',
'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']
```
### Cyclic
For Cyclic maps, we want to start and end on the same color, and meet a
symmetric center point in the middle. \(L^*\) should change monotonically
from start to middle, and inversely from middle to end. It should be symmetric
on the increasing and decreasing side, and only differ in hue. At the ends and
middle, \(L^*\) will reverse direction, which should be smoothed in
\(L^*\) space to reduce artifacts. See [[kovesi-colormaps]](#kovesi-colormaps) for more
information on the design of cyclic maps.
The often-used HSV colormap is included in this set of colormaps, although it
is not symmetric to a center point. Additionally, the \(L^*\) values vary
widely throughout the colormap, making it a poor choice for representing data
for viewers to see perceptually. See an extension on this idea at
[[mycarta-jet]](#mycarta-jet).
``` python
cmaps['Cyclic'] = ['twilight', 'twilight_shifted', 'hsv']
```
### Qualitative
Qualitative colormaps are not aimed at being perceptual maps, but looking at the
lightness parameter can verify that for us. The \(L^*\) values move all over
the place throughout the colormap, and are clearly not monotonically increasing.
These would not be good options for use as perceptual colormaps.
``` python
cmaps['Qualitative'] = ['Pastel1', 'Pastel2', 'Paired', 'Accent',
'Dark2', 'Set1', 'Set2', 'Set3',
'tab10', 'tab20', 'tab20b', 'tab20c']
```
### Miscellaneous
Some of the miscellaneous colormaps have particular uses for which
they have been created. For example, gist_earth, ocean, and terrain
all seem to be created for plotting topography (green/brown) and water
depths (blue) together. We would expect to see a divergence in these
colormaps, then, but multiple kinks may not be ideal, such as in
gist_earth and terrain. CMRmap was created to convert well to
grayscale, though it does appear to have some small kinks in
\(L^*\). cubehelix was created to vary smoothly in both lightness
and hue, but appears to have a small hump in the green hue area.
The often-used jet colormap is included in this set of colormaps. We can see
that the \(L^*\) values vary widely throughout the colormap, making it a
poor choice for representing data for viewers to see perceptually. See an
extension on this idea at [[mycarta-jet]](#mycarta-jet).
``` python
cmaps['Miscellaneous'] = [
'flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern',
'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg',
'gist_rainbow', 'rainbow', 'jet', 'nipy_spectral', 'gist_ncar']
```
First, we'll show the range of each colormap. Note that some seem
to change more "quickly" than others.
``` python
nrows = max(len(cmap_list) for cmap_category, cmap_list in cmaps.items())
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(cmap_category, cmap_list, nrows):
fig, axes = plt.subplots(nrows=nrows)
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99)
axes[0].set_title(cmap_category + ' colormaps', fontsize=14)
for ax, name in zip(axes, cmap_list):
ax.imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
pos = list(ax.get_position().bounds)
x_text = pos[0] - 0.01
y_text = pos[1] + pos[3]/2.
fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)
# Turn off *all* ticks & spines, not just the ones with colormaps.
for ax in axes:
ax.set_axis_off()
for cmap_category, cmap_list in cmaps.items():
plot_color_gradients(cmap_category, cmap_list, nrows)
plt.show()
```
- ![sphx_glr_colormaps_001](https://matplotlib.org/_images/sphx_glr_colormaps_001.png)
- ![sphx_glr_colormaps_002](https://matplotlib.org/_images/sphx_glr_colormaps_002.png)
- ![sphx_glr_colormaps_003](https://matplotlib.org/_images/sphx_glr_colormaps_003.png)
- ![sphx_glr_colormaps_004](https://matplotlib.org/_images/sphx_glr_colormaps_004.png)
- ![sphx_glr_colormaps_005](https://matplotlib.org/_images/sphx_glr_colormaps_005.png)
- ![sphx_glr_colormaps_006](https://matplotlib.org/_images/sphx_glr_colormaps_006.png)
- ![sphx_glr_colormaps_007](https://matplotlib.org/_images/sphx_glr_colormaps_007.png)
## Lightness of matplotlib colormaps
Here we examine the lightness values of the matplotlib colormaps.
Note that some documentation on the colormaps is available
([[list-colormaps]](#list-colormaps)).
``` python
mpl.rcParams.update({'font.size': 12})
# Number of colormap per subplot for particular cmap categories
_DSUBS = {'Perceptually Uniform Sequential': 5, 'Sequential': 6,
'Sequential (2)': 6, 'Diverging': 6, 'Cyclic': 3,
'Qualitative': 4, 'Miscellaneous': 6}
# Spacing between the colormaps of a subplot
_DC = {'Perceptually Uniform Sequential': 1.4, 'Sequential': 0.7,
'Sequential (2)': 1.4, 'Diverging': 1.4, 'Cyclic': 1.4,
'Qualitative': 1.4, 'Miscellaneous': 1.4}
# Indices to step through colormap
x = np.linspace(0.0, 1.0, 100)
# Do plot
for cmap_category, cmap_list in cmaps.items():
# Do subplots so that colormaps have enough space.
# Default is 6 colormaps per subplot.
dsub = _DSUBS.get(cmap_category, 6)
nsubplots = int(np.ceil(len(cmap_list) / dsub))
# squeeze=False to handle similarly the case of a single subplot
fig, axes = plt.subplots(nrows=nsubplots, squeeze=False,
figsize=(7, 2.6*nsubplots))
for i, ax in enumerate(axes.flat):
locs = [] # locations for text labels
for j, cmap in enumerate(cmap_list[i*dsub:(i+1)*dsub]):
# Get RGB values for colormap and convert the colormap in
# CAM02-UCS colorspace. lab[0, :, 0] is the lightness.
rgb = cm.get_cmap(cmap)(x)[np.newaxis, :, :3]
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
# Plot colormap L values. Do separately for each category
# so each plot can be pretty. To make scatter markers change
# color along plot:
# http://stackoverflow.com/questions/8202605/
if cmap_category == 'Sequential':
# These colormaps all start at high lightness but we want them
# reversed to look nice in the plot, so reverse the order.
y_ = lab[0, ::-1, 0]
c_ = x[::-1]
else:
y_ = lab[0, :, 0]
c_ = x
dc = _DC.get(cmap_category, 1.4) # cmaps horizontal spacing
ax.scatter(x + j*dc, y_, c=c_, cmap=cmap, s=300, linewidths=0.0)
# Store locations for colormap labels
if cmap_category in ('Perceptually Uniform Sequential',
'Sequential'):
locs.append(x[-1] + j*dc)
elif cmap_category in ('Diverging', 'Qualitative', 'Cyclic',
'Miscellaneous', 'Sequential (2)'):
locs.append(x[int(x.size/2.)] + j*dc)
# Set up the axis limits:
# * the 1st subplot is used as a reference for the x-axis limits
# * lightness values goes from 0 to 100 (y-axis limits)
ax.set_xlim(axes[0, 0].get_xlim())
ax.set_ylim(0.0, 100.0)
# Set up labels for colormaps
ax.xaxis.set_ticks_position('top')
ticker = mpl.ticker.FixedLocator(locs)
ax.xaxis.set_major_locator(ticker)
formatter = mpl.ticker.FixedFormatter(cmap_list[i*dsub:(i+1)*dsub])
ax.xaxis.set_major_formatter(formatter)
ax.xaxis.set_tick_params(rotation=50)
ax.set_xlabel(cmap_category + ' colormaps', fontsize=14)
fig.text(0.0, 0.55, 'Lightness $L^*$', fontsize=12,
transform=fig.transFigure, rotation=90)
fig.tight_layout(h_pad=0.0, pad=1.5)
plt.show()
```
- ![sphx_glr_colormaps_008](https://matplotlib.org/_images/sphx_glr_colormaps_008.png)
- ![sphx_glr_colormaps_009](https://matplotlib.org/_images/sphx_glr_colormaps_009.png)
- ![sphx_glr_colormaps_010](https://matplotlib.org/_images/sphx_glr_colormaps_010.png)
- ![sphx_glr_colormaps_011](https://matplotlib.org/_images/sphx_glr_colormaps_011.png)
- ![sphx_glr_colormaps_012](https://matplotlib.org/_images/sphx_glr_colormaps_012.png)
- ![sphx_glr_colormaps_013](https://matplotlib.org/_images/sphx_glr_colormaps_013.png)
- ![sphx_glr_colormaps_014](https://matplotlib.org/_images/sphx_glr_colormaps_014.png)
## Grayscale conversion
It is important to pay attention to conversion to grayscale for color
plots, since they may be printed on black and white printers. If not
carefully considered, your readers may end up with indecipherable
plots because the grayscale changes unpredictably through the
colormap.
Conversion to grayscale is done in many different ways [[bw]](#bw). Some of the
better ones use a linear combination of the rgb values of a pixel, but
weighted according to how we perceive color intensity. A nonlinear method of
conversion to grayscale is to use the \(L^*\) values of the pixels. In
general, similar principles apply for this question as they do for presenting
one's information perceptually; that is, if a colormap is chosen that is
monotonically increasing in \(L^*\) values, it will print in a reasonable
manner to grayscale.
With this in mind, we see that the Sequential colormaps have reasonable
representations in grayscale. Some of the Sequential2 colormaps have decent
enough grayscale representations, though some (autumn, spring, summer,
winter) have very little grayscale change. If a colormap like this was used
in a plot and then the plot was printed to grayscale, a lot of the
information may map to the same gray values. The Diverging colormaps mostly
vary from darker gray on the outer edges to white in the middle. Some
(PuOr and seismic) have noticeably darker gray on one side than the other
and therefore are not very symmetric. coolwarm has little range of gray scale
and would print to a more uniform plot, losing a lot of detail. Note that
overlaid, labeled contours could help differentiate between one side of the
colormap vs. the other since color cannot be used once a plot is printed to
grayscale. Many of the Qualitative and Miscellaneous colormaps, such as
Accent, hsv, and jet, change from darker to lighter and back to darker gray
throughout the colormap. This would make it impossible for a viewer to
interpret the information in a plot once it is printed in grayscale.
``` python
mpl.rcParams.update({'font.size': 14})
# Indices to step through colormap.
x = np.linspace(0.0, 1.0, 100)
gradient = np.linspace(0, 1, 256)
gradient = np.vstack((gradient, gradient))
def plot_color_gradients(cmap_category, cmap_list):
fig, axes = plt.subplots(nrows=len(cmap_list), ncols=2)
fig.subplots_adjust(top=0.95, bottom=0.01, left=0.2, right=0.99,
wspace=0.05)
fig.suptitle(cmap_category + ' colormaps', fontsize=14, y=1.0, x=0.6)
for ax, name in zip(axes, cmap_list):
# Get RGB values for colormap.
rgb = cm.get_cmap(plt.get_cmap(name))(x)[np.newaxis, :, :3]
# Get colormap in CAM02-UCS colorspace. We want the lightness.
lab = cspace_converter("sRGB1", "CAM02-UCS")(rgb)
L = lab[0, :, 0]
L = np.float32(np.vstack((L, L, L)))
ax[0].imshow(gradient, aspect='auto', cmap=plt.get_cmap(name))
ax[1].imshow(L, aspect='auto', cmap='binary_r', vmin=0., vmax=100.)
pos = list(ax[0].get_position().bounds)
x_text = pos[0] - 0.01
y_text = pos[1] + pos[3]/2.
fig.text(x_text, y_text, name, va='center', ha='right', fontsize=10)
# Turn off *all* ticks & spines, not just the ones with colormaps.
for ax in axes.flat:
ax.set_axis_off()
plt.show()
for cmap_category, cmap_list in cmaps.items():
plot_color_gradients(cmap_category, cmap_list)
```
- ![sphx_glr_colormaps_015](https://matplotlib.org/_images/sphx_glr_colormaps_015.png)
- ![sphx_glr_colormaps_016](https://matplotlib.org/_images/sphx_glr_colormaps_016.png)
- ![sphx_glr_colormaps_017](https://matplotlib.org/_images/sphx_glr_colormaps_017.png)
- ![sphx_glr_colormaps_018](https://matplotlib.org/_images/sphx_glr_colormaps_018.png)
- ![sphx_glr_colormaps_019](https://matplotlib.org/_images/sphx_glr_colormaps_019.png)
- ![sphx_glr_colormaps_020](https://matplotlib.org/_images/sphx_glr_colormaps_020.png)
- ![sphx_glr_colormaps_021](https://matplotlib.org/_images/sphx_glr_colormaps_021.png)
## Color vision deficiencies
There is a lot of information available about color blindness (*e.g.*,
[[colorblindness]](#colorblindness)). Additionally, there are tools available to convert images
to how they look for different types of color vision deficiencies.
The most common form of color vision deficiency involves differentiating
between red and green. Thus, avoiding colormaps with both red and green will
avoid many problems in general.
## References
---
[colorcet]([1](#id[2](#id4)), 2) [https://colorcet.pyviz.org](https://colorcet.pyviz.org)
---
[[Ware]](#id3)[http://ccom.unh.edu/sites/default/files/publications/Ware_1988_CGA_Color_sequences_univariate_maps.pdf](http://ccom.unh.edu/sites/default/files/publications/Ware_1988_CGA_Color_sequences_univariate_maps.pdf)
---
[[Moreland]](#id6)[http://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf](http://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf)
---
[[list-colormaps]](#id11)[https://gist.github.com/endolith/2719900#id7](https://gist.github.com/endolith/2719900#id7)
---
[[mycarta-banding]](#id7)[https://mycarta.wordpress.com/2012/10/14/the-rainbow-is-deadlong-live-the-rainbow-part-4-cie-lab-heated-body/](https://mycarta.wordpress.com/2012/10/14/the-rainbow-is-deadlong-live-the-rainbow-part-4-cie-lab-heated-body/)
---
[mycarta-jet]([1](#id9), [2](#id10)) [https://mycarta.wordpress.com/2012/10/06/the-rainbow-is-deadlong-live-the-rainbow-part-3/](https://mycarta.wordpress.com/2012/10/06/the-rainbow-is-deadlong-live-the-rainbow-part-3/)
---
[[kovesi-colormaps]](#id8)[https://arxiv.org/abs/1509.03700](https://arxiv.org/abs/1509.03700)
---
[[bw]](#id12)[http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/](http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/)
---
[[colorblindness]](#id13)[http://www.color-blindness.com/](http://www.color-blindness.com/)
---
[[IBM]](#id5)[https://doi.org/10.1109/VISUAL.1995.480803](https://doi.org/10.1109/VISUAL.1995.480803)
---
[[palettable]](#id1)[https://jiffyclub.github.io/palettable/](https://jiffyclub.github.io/palettable/)
**Total running time of the script:** ( 0 minutes 9.320 seconds)
## Download
- [Download Python source code: colormaps.py](https://matplotlib.org/_downloads/9df0748eeda573fbccab51a7272f7d81/colormaps.py)
- [Download Jupyter notebook: colormaps.ipynb](https://matplotlib.org/_downloads/6024d841c77bf197ffe5612254186669/colormaps.ipynb)

View File

@@ -0,0 +1,135 @@
---
sidebarDepth: 3
sidebar: auto
---
# Specifying Colors
Matplotlib recognizes the following formats to specify a color:
- an RGB or RGBA (red, green, blue, alpha) tuple of float values in ``[0, 1]``
(e.g., ``(0.1, 0.2, 0.5)`` or ``(0.1, 0.2, 0.5, 0.3)``);
- a hex RGB or RGBA string (e.g., ``'#0f0f0f'`` or ``'#0f0f0f80'``;
case-insensitive);
- a string representation of a float value in ``[0, 1]`` inclusive for gray
level (e.g., ``'0.5'``);
- one of ``{'b', 'g', 'r', 'c', 'm', 'y', 'k', 'w'}``;
- a X11/CSS4 color name (case-insensitive);
- a name from the [xkcd color survey](https://xkcd.com/color/rgb/), prefixed with ``'xkcd:'`` (e.g.,
``'xkcd:sky blue'``; case insensitive);
- one of the Tableau Colors from the 'T10' categorical palette (the default
color cycle): ``{'tab:blue', 'tab:orange', 'tab:green', 'tab:red',
'tab:purple', 'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan'}``
(case-insensitive);
- a "CN" color spec, i.e. ``'C'`` followed by a number, which is an index into
the default property cycle (``matplotlib.rcParams['axes.prop_cycle']``); the
indexing is intended to occur at rendering time, and defaults to black if the
cycle does not include color.
"Red", "Green", and "Blue" are the intensities of those colors, the combination
of which span the colorspace.
How "Alpha" behaves depends on the ``zorder`` of the Artist. Higher
``zorder`` Artists are drawn on top of lower Artists, and "Alpha" determines
whether the lower artist is covered by the higher.
If the old RGB of a pixel is ``RGBold`` and the RGB of the
pixel of the Artist being added is ``RGBnew`` with Alpha ``alpha``,
then the RGB of the pixel is updated to:
``RGB = RGBOld * (1 - Alpha) + RGBnew * Alpha``. Alpha
of 1 means the old color is completely covered by the new Artist, Alpha of 0
means that pixel of the Artist is transparent.
For more information on colors in matplotlib see
- the [Color Demo](https://matplotlib.orggallery/color/color_demo.html) example;
- the [``matplotlib.colors``](https://matplotlib.orgapi/colors_api.html#module-matplotlib.colors) API;
- the [List of named colors](https://matplotlib.orggallery/color/named_colors.html) example.
## "CN" color selection
"CN" colors are converted to RGBA as soon as the artist is created. For
example,
``` python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
th = np.linspace(0, 2*np.pi, 128)
def demo(sty):
mpl.style.use(sty)
fig, ax = plt.subplots(figsize=(3, 3))
ax.set_title('style: {!r}'.format(sty), color='C0')
ax.plot(th, np.cos(th), 'C1', label='C1')
ax.plot(th, np.sin(th), 'C2', label='C2')
ax.legend()
demo('default')
demo('seaborn')
```
- ![sphx_glr_colors_001](https://matplotlib.org/_images/sphx_glr_colors_001.png)
- ![sphx_glr_colors_002](https://matplotlib.org/_images/sphx_glr_colors_002.png)
will use the first color for the title and then plot using the second
and third colors of each style's ``mpl.rcParams['axes.prop_cycle']``.
## xkcd v X11/CSS4
The xkcd colors are derived from a user survey conducted by the
webcomic xkcd. [Details of the survey are available on the xkcd blog](https://blog.xkcd.com/2010/05/03/color-survey-results/).
Out of 148 colors in the CSS color list, there are 95 name collisions
between the X11/CSS4 names and the xkcd names, all but 3 of which have
different hex values. For example ``'blue'`` maps to ``'#0000FF'``
where as ``'xkcd:blue'`` maps to ``'#0343DF'``. Due to these name
collisions all of the xkcd colors have ``'xkcd:'`` prefixed. As noted in
the blog post, while it might be interesting to re-define the X11/CSS4 names
based on such a survey, we do not do so unilaterally.
The name collisions are shown in the table below; the color names
where the hex values agree are shown in bold.
``` python
import matplotlib._color_data as mcd
import matplotlib.patches as mpatch
overlap = {name for name in mcd.CSS4_COLORS
if "xkcd:" + name in mcd.XKCD_COLORS}
fig = plt.figure(figsize=[4.8, 16])
ax = fig.add_axes([0, 0, 1, 1])
for j, n in enumerate(sorted(overlap, reverse=True)):
weight = None
cn = mcd.CSS4_COLORS[n]
xkcd = mcd.XKCD_COLORS["xkcd:" + n].upper()
if cn == xkcd:
weight = 'bold'
r1 = mpatch.Rectangle((0, j), 1, 1, color=cn)
r2 = mpatch.Rectangle((1, j), 1, 1, color=xkcd)
txt = ax.text(2, j+.5, ' ' + n, va='center', fontsize=10,
weight=weight)
ax.add_patch(r1)
ax.add_patch(r2)
ax.axhline(j, color='k')
ax.text(.5, j + 1.5, 'X11', ha='center', va='center')
ax.text(1.5, j + 1.5, 'xkcd', ha='center', va='center')
ax.set_xlim(0, 3)
ax.set_ylim(0, j + 2)
ax.axis('off')
```
![sphx_glr_colors_003](https://matplotlib.org/_images/sphx_glr_colors_003.png)
## Download
- [Download Python source code: colors.py](https://matplotlib.org/_downloads/8fb6dfde0db5f6422a7627d0d4e328b2/colors.py)
- [Download Jupyter notebook: colors.ipynb](https://matplotlib.org/_downloads/04907c28d4180c02e547778b9aaee05d/colors.ipynb)