.. _colormapnorm-tutorial: Colormap Normaliztions ================================ 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 :func:`matplotlib.colors` module. The default normalization is :func:`matplotlib.colors.Normalize`. The artists that map data to color pass the arguments *vmin* and *vmax* to :func:`matplotlib.colors.Normalize`. We can substnatiate the normalization and see what it returns. In this case it returns 0.5: .. ipython:: 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 when there are changes across disparate scales that we still want to be able to see. Using :func:`colors.LogNorm` normalizes the data by :math:`log_{10}`. In the example below, there are two bumps, one much smaller than the other. Using :func:`colors.LogNorm`, the shape and location of each bump can clearly be seen: .. plot:: users/plotting/examples/colormap_normalizations_lognorm.py :include-source: Symetric 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 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. .. plot:: users/plotting/examples/colormap_normalizations_symlognorm.py :include-source: Power-law --------------------------------- Sometimes it is useful to remap the colors onto a power-law relationship (i.e. :math:`y=x^{\gamma}`, where :math:`\gamma` is the power). For this we use the :func:`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. .. plot:: users/plotting/examples/colormap_normalizations_power.py :include-source: Discrete bounds --------------------------------- Another normaization that comes with matplolib is :func:`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: .. ipython:: In [2]: import matplotlib.colors as colors In [3]: bounds = np.array([-0.25, -0.125, 0, 0.5, 1]) In [4]: norm = colors.BoundaryNorm(boundaries=bounds, ncolors=4) In [5]: 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. .. plot:: users/plotting/examples/colormap_normalizations_bounds.py :include-source: Custom normalization: Two linear ranges ----------------------------------------- It is possible to define your own normalization. This example plots the same data as the :func:`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 :func:`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. .. plot:: users/plotting/examples/colormap_normalizations_custom.py :include-source: