You are reading an old version of the documentation (v1.5.0). For the latest version see https://matplotlib.org/stable/

Learn what to expect in the new updates

Objects that use colormaps by default linearly map the colors in the
colormap from data values *vmin* to *vmax*. For example:

```
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
[0,1] occuring first, and then mapping onto the indices in the
colormap. Normalizations are defined as part of
`matplotlib.colors()`

module. The default normalization is
`matplotlib.colors.Normalize()`

.

The artists that map data to
color pass the arguments *vmin* and *vmax* to
`matplotlib.colors.Normalize()`

. We can substnatiate the
normalization and see what it returns. In this case it returns 0.5:

```
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.

One of the most common transformations is to plot data by taking its
logarithm (to the base-10). This transformation is useful when there
are changes across disparate scales that we still want to be able to
see. Using `colors.LogNorm()`

normalizes the data by
. In the example below, there are two bumps, one much
smaller than the other. Using `colors.LogNorm()`

, the shape and
location of each bump can clearly be seen:

```
"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
'''
Lognorm: Instead of pcolor log10(Z1) you can have colorbars that have
the exponential labels using a norm.
'''
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 = bivariate_normal(X, Y, 0.1, 0.2, 1.0, 1.0) + \
0.1 * bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolor(X, Y, Z1,
norm=colors.LogNorm(vmin=Z1.min(), vmax=Z1.max()),
cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')
pcm = ax[1].pcolor(X, Y, Z1, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
fig.show()
```

(Source code, png, hires.png, pdf)

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 small numbers. i.e. 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 values close to zero tend toward infinity, there is a need
to have a range around zero that is linear. 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.

```
"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
"""
SymLogNorm: two humps, one negative and one positive, The positive
with 5-times the amplitude. Linearly, you cannot see detail in the
negative hump. Here we logarithmically scale the positive and
negative data separately.
Note that colorbar labels do not come out looking very good.
"""
N=100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1,
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, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[1], extend='both')
fig.show()
```

(Source code, png, hires.png, pdf)

Sometimes it is useful to remap the colors onto a power-law
relationship (i.e. , where is the
power). For this we use the `colors.PowerNorm()`

. It takes as an
argument *gamma* ( *gamma* == 1.0 will just yield the defalut linear
normalization):

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 explictly be made aware that they have been used.

```
"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
'''
PowerNorm: Here a power-law trend in X partially obscures a rectified
sine wave in Y. We can remove the power law using a PowerNorm.
'''
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=1./2.),
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')
fig.show()
```

(Source code, png, hires.png, pdf)

Another normaization that comes with matplolib 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, if:

```
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.

```
"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
'''
BoundaryNorm: For this one you provide the boundaries for your colors,
and the Norm puts the first color in between the first pair, the
second color between the second pair, etc.
'''
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, Z1,
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, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
pcm = ax[2].pcolormesh(X, Y, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
fig.show()
```

(Source code, png, hires.png, pdf)

It is possible to define your own normalization. This example
plots the same data as the `colors:SymLogNorm()`

example, but
a different linear map is used for the negative data values than
the positive. (Note that this example is simple, and does not account
for the edge cases like masked data or invalid values of *vmin* and
*vmax*)

Note

This may appear soon as `colors.OffsetNorm()`

As above, non-symetric mapping of data to color is non-standard practice for quantitative data, and should only be used advisedly. A practical example is having an ocean/land colormap where the land and ocean data span different ranges.

```
"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
N = 100
'''
Custom Norm: An example with a customized normalization. This one
uses the example above, and normalizes the negative data differently
from the positive.
'''
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
# Example of making your own norm. Also see matplotlib.colors.
# From Joe Kington: This one gives two different linear ramps:
class MidpointNormalize(colors.Normalize):
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
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.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
#####
fig, ax = plt.subplots(2, 1)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=MidpointNormalize(midpoint=0.),
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both')
pcm = ax[1].pcolormesh(X, Y, Z1, cmap='RdBu_r', vmin=-np.max(Z1))
fig.colorbar(pcm, ax=ax[1], extend='both')
fig.show()
```

(Source code, png, hires.png, pdf)