From daa9c59204197f2b514c12b427923a195c7a9d82 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 21 Aug 2018 12:33:56 -0700 Subject: [PATCH 1/6] DOC: colormap-manipulation tutorial --- tutorials/colors/colormap-manipulation.py | 169 ++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 tutorials/colors/colormap-manipulation.py diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py new file mode 100644 index 000000000000..c8a30498eb96 --- /dev/null +++ b/tutorials/colors/colormap-manipulation.py @@ -0,0 +1,169 @@ +""" +************************************************* +Manipulating and Creating Colormaps in Matplotlib +************************************************* + +Matplotlib colormaps are implimented as a class, which makes them quite +flexible, but ocasionally opaque to users as to how to create and/or +manipulate them. This opacity is not helped in the library by the fact that +the named colormaps are accessed via `.matplotlib.cm.get_cmap` module, whereas +the colormap class itself is defined in `.matplotlin.colors.Colormap`! + +Getting colormaps and accessing their values +============================================ + +First, getting a named colormap, most of which are listed in +:doc:`/tutorials/colors/colormaps` requires the use of +`.matplotlib.cm.get_cmap`, which returns a +:class:`.matplotlib.colors.ListedColormap` object. The second argument gives +the size of the list of colors used to define the colormap. +""" + +import numpy as np +import matplotlib as mpl +import matplotlib.pyplot as plt +from matplotlib import cm +from matplotlib.colors import ListedColormap, LinearSegmentedColormap +from collections import OrderedDict + +viridis = cm.get_cmap('viridis', 12) +print(viridis) + +############################################################################## +# This list of colors can be directly accessed using the ``colors`` property, +# or it can be indirectly acccessed by calling the object. Note that the list +# is of the form of an RGBA Nx4 array, where N is the length of the colormap. + +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))) + +############################################################################## +# The colormap is a lookup table, so "oversampling" the colormap returns +# nearest-neighbor interpolation (note the repeated colors in the list below) + +print('viridis(np.linspace(0, 1, 15))', viridis(np.linspace(0, 1, 15))) + +############################################################################## +# Creating a new ListedColormap: Colormap carpentry +# ================================================= +# +# 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` 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: + +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): + np.random.seed(19680801) + data = np.random.randn(30,30) + + fig, axs = plt.subplots(1, 2, figsize=(6, 3), constrained_layout=True) + for [ax, cm] in zip(axs, cms): + psm = ax.pcolormesh(data, cmap=cm, rasterized=True, vmin=-4, vmax=4) + fig.colorbar(psm, ax=ax) + plt.show() + +plot_examples([viridis, newcmp]) + +############################################################################## +# We can easily reduce the range of a colormap; here we choose the middle +# 0.5 of the colormap. + +viridis = cm.get_cmap('viridis', 256) +newcmp = ListedColormap(viridis(np.linspace(0.25, 0.75, 256))) +plot_examples([viridis, newcmp]) + +############################################################################## +# and we can easily paste together two colormaps: + +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]) + +############################################################################## +# LinearSegmented colormaps +# ========================= +# +# LinearSegmented colormaps are an alternate way to specify colormaps that +# specify anchor points for linear ramps for each of RGB and optionally, alpha +# (RGBA). +# +# The format to specify these colormaps is a bit complicated to allow +# discontinuities at the anchor points. First, with no discontinuities: + +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) + +############################################################################# +# However, consider the case where the third column is different than the +# second. The linear interpolation between red[i, 0] and red[i+1, 0] is +# from red[i, 2] to red[i+1, 1]. This format allows us to have +# discontinuities in the colormap at the anchor points; in this case +# between 0 and 0.5, the linear interpolation 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, which happens between the last +# element of the first anchor and the first element of the second anchor. + +cdict['red'] = [[0.0, 0.0, 0.3], + [0.5, 1.0, 0.9], + [1.0, 1.0, 1.0]] +plot_linearmap(cdict) + + +############################################################################# +# +# ------------ +# +# References +# """""""""" +# +# The use of the following functions, methods, classes and modules is shown +# in this example: + +import matplotlib +matplotlib.axes.Axes.pcolormesh +matplotlib.figure.Figure.colorbar +matplotlib.colors +matplotlib.colors.LinearSegmentedColormap +matplotlib.colors.ListedColormap +matplotlib.cm +matplotlib.cm.ScalarMappable.get_cmap +matplotlib.pyplot.register_cmap +matplotlib.cm.register_cmap From 6d2a7bc899b3d281395e0a2bc31a39553a6a7fb7 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Tue, 21 Aug 2018 14:58:57 -0700 Subject: [PATCH 2/6] DOC: colormap-manipulation tutorial --- tutorials/colors/colormap-manipulation.py | 65 ++++++++++++++++------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index c8a30498eb96..171e42d579ee 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -1,13 +1,17 @@ """ -************************************************* -Manipulating and Creating Colormaps in Matplotlib -************************************************* +******************************** +Creating Colormaps in Matplotlib +******************************** Matplotlib colormaps are implimented as a class, which makes them quite -flexible, but ocasionally opaque to users as to how to create and/or +flexible, but opaque to users as to how to create and/or manipulate them. This opacity is not helped in the library by the fact that the named colormaps are accessed via `.matplotlib.cm.get_cmap` module, whereas -the colormap class itself is defined in `.matplotlin.colors.Colormap`! +the colormap class itself is defined in `.matplotlib.colors.Colormap`! + +Fortunately, the way to create colormaps is quite straight forward, by creating +an instance of class `.ListedColormap` using a Nx4 numpy array of values +between 0 and 1 to represent the RGBA values of the colormap. Getting colormaps and accessing their values ============================================ @@ -16,7 +20,8 @@ :doc:`/tutorials/colors/colormaps` requires the use of `.matplotlib.cm.get_cmap`, which returns a :class:`.matplotlib.colors.ListedColormap` object. The second argument gives -the size of the list of colors used to define the colormap. +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. """ import numpy as np @@ -30,9 +35,17 @@ print(viridis) ############################################################################## -# This list of colors can be directly accessed using the ``colors`` property, -# or it can be indirectly acccessed by calling the object. Note that the list -# is of the form of an RGBA Nx4 array, where N is the length of the colormap. +# The object ``viridis`` is a callable, that when passed a float between +# 0 and 1 returns an RGBA value from the colormap: + +print(viridis(0.56)) + +############################################################################## +# The list of colors that comprise the colormap can be directly accessed using +# the ``colors`` property, +# or it can be acccessed 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. print('viridis.colors', viridis.colors) print('viridis(range(12))', viridis(range(12))) @@ -45,8 +58,8 @@ print('viridis(np.linspace(0, 1, 15))', viridis(np.linspace(0, 1, 15))) ############################################################################## -# Creating a new ListedColormap: Colormap carpentry -# ================================================= +# Creating a new ListedColormap +# ============================= # # This is essential the inverse operation of the above where we supply a # Nx4 numpy array with all values between 0 and 1, @@ -64,6 +77,9 @@ newcmp = ListedColormap(newcolors) def plot_examples(cms): + """ + helper function to plot two colormaps + """ np.random.seed(19680801) data = np.random.randn(30,30) @@ -84,7 +100,7 @@ def plot_examples(cms): plot_examples([viridis, newcmp]) ############################################################################## -# and we can easily paste together two colormaps: +# and we can easily concatenate two colormaps: top = cm.get_cmap('Oranges_r', 128) bottom = cm.get_cmap('Blues', 128) @@ -94,12 +110,25 @@ def plot_examples(cms): newcmp = ListedColormap(newcolors, name='OrangeBlue') plot_examples([viridis, newcmp]) +############################################################################## +# Of course we need not start from a named colormap, we just need to create +# the Nx4 array to pass to `.ListedColormap`. Here we create a +# brown colormap that goes to white.... + +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]) + ############################################################################## # LinearSegmented colormaps # ========================= # -# LinearSegmented colormaps are an alternate way to specify colormaps that -# specify anchor points for linear ramps for each of RGB and optionally, alpha +# `.LinearSegmentedColormap` have an alternate way to specify colormaps that +# specify anchor points for linear ramps for each of RGB, and optionally, alpha # (RGBA). # # The format to specify these colormaps is a bit complicated to allow @@ -142,8 +171,8 @@ def plot_linearmap(cdict): # element of the first anchor and the first element of the second anchor. cdict['red'] = [[0.0, 0.0, 0.3], - [0.5, 1.0, 0.9], - [1.0, 1.0, 1.0]] + [0.5, 1.0, 0.9], + [1.0, 1.0, 1.0]] plot_linearmap(cdict) @@ -164,6 +193,4 @@ def plot_linearmap(cdict): matplotlib.colors.LinearSegmentedColormap matplotlib.colors.ListedColormap matplotlib.cm -matplotlib.cm.ScalarMappable.get_cmap -matplotlib.pyplot.register_cmap -matplotlib.cm.register_cmap +matplotlib.cm.get_cmap From f58f5f3fba1557dd784bb36db30d9a526c604ef3 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Wed, 22 Aug 2018 10:57:43 -0700 Subject: [PATCH 3/6] DOC: move custom_colormap --- .flake8 | 3 ++- .../custom_cmap.py | 3 +++ lib/matplotlib/cm.py | 9 +++++-- lib/matplotlib/colors.py | 27 +++++++++++++------ tutorials/colors/colormap-manipulation.py | 14 +++++----- 5 files changed, 39 insertions(+), 17 deletions(-) rename examples/{images_contours_and_fields => color}/custom_cmap.py (98%) diff --git a/.flake8 b/.flake8 index 372a6f2e883a..9d3ff9b8462d 100644 --- a/.flake8 +++ b/.flake8 @@ -86,6 +86,7 @@ per-file-ignores = tutorials/advanced/transforms_tutorial.py: E402, E501 tutorials/colors/colormaps.py: E501 tutorials/colors/colors.py: E402 + tutorials/colors/colormap-manipulation.py: E402 tutorials/intermediate/artists.py: E402, E501 tutorials/intermediate/constrainedlayout_guide.py: E402, E501 tutorials/intermediate/gridspec.py: E402, E501 @@ -114,6 +115,7 @@ per-file-ignores = examples/color/color_demo.py: E402 examples/color/colorbar_basics.py: E402 examples/color/colormap_reference.py: E402 + examples/color/custom_cmap.py: E402 examples/color/named_colors.py: E402 examples/event_handling/data_browser.py: E501 examples/event_handling/path_editor.py: E501 @@ -129,7 +131,6 @@ per-file-ignores = examples/images_contours_and_fields/contourf_demo.py: E402, E501 examples/images_contours_and_fields/contourf_hatching.py: E402 examples/images_contours_and_fields/contourf_log.py: E402 - examples/images_contours_and_fields/custom_cmap.py: E402 examples/images_contours_and_fields/demo_bboximage.py: E402 examples/images_contours_and_fields/image_clip_path.py: E402 examples/images_contours_and_fields/image_demo.py: E402 diff --git a/examples/images_contours_and_fields/custom_cmap.py b/examples/color/custom_cmap.py similarity index 98% rename from examples/images_contours_and_fields/custom_cmap.py rename to examples/color/custom_cmap.py index f01a4e8a8e64..eb3727d92786 100644 --- a/examples/images_contours_and_fields/custom_cmap.py +++ b/examples/color/custom_cmap.py @@ -3,6 +3,9 @@ Creating a colormap from a list of colors ========================================= +For more detail on creating and manipulating colormaps see +:doc:`/tutorials/colors/colormap-manipulation`. + Creating a :doc:`colormap ` from a list of colors can be done with the :meth:`~.colors.LinearSegmentedColormap.from_list` method of diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index 20dbbcbcc84b..f5c60685e333 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -1,8 +1,13 @@ """ Builtin colormaps, colormap handling utilities, and the `ScalarMappable` mixin. -See :doc:`/gallery/color/colormap_reference` for a list of builtin colormaps. -See :doc:`/tutorials/colors/colormaps` for an in-depth discussion of colormaps. + - See :doc:`/gallery/color/colormap_reference` for a list of builtin + colormaps. + - See :doc:`/tutorials/colors/colormaps` for an in-depth discussion of + choosing colormaps. + - See :doc:`/tutorials/colors/colormap-manipulation` for an in-depth + discussion of how to manipulate colormaps. + """ import functools diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py index 82969ed18cb7..ef51fc20bdd7 100644 --- a/lib/matplotlib/colors.py +++ b/lib/matplotlib/colors.py @@ -6,14 +6,25 @@ This module includes functions and classes for color specification conversions, and for mapping numbers to colors in a 1-D array of colors called -a colormap. Colormapping typically involves two steps: a data array is first -mapped onto the range 0-1 using an instance of :class:`Normalize` or of a -subclass; then this number in the 0-1 range is mapped to a color using an -instance of a subclass of :class:`Colormap`. Two are provided here: -:class:`LinearSegmentedColormap`, which is used to generate all the built-in -colormap instances, but is also useful for making custom colormaps, and -:class:`ListedColormap`, which is used for generating a custom colormap from a -list of color specifications. +a colormap. + +Mapping data onto colors using a colormap typically involves two steps: +a data array is first mapped onto the range 0-1 using a subclass of +:class:`Normalize`, then this number is mapped to a color using +a subclass of :class:`Colormap`. Two are provided here: +:class:`LinearSegmentedColormap`, which uses piecewise-linear interpolation +to define colormaps, and :class:`ListedColormap`, which makes a colormap +from a list of colors. + +.. seealso:: + + :doc:`/tutorials/colors/colormap-manipulation` for examples of how to + make colormaps and + + :doc:`/tutorials/colors/colormaps` for a list of built-in colormaps. + + :doc:`/tutorials/colors/colormapnorms` for more details about data + normalization The module also provides functions for checking whether an object can be interpreted as a color (:func:`is_color_like`), for converting such an object diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index 171e42d579ee..466a6bc06d3c 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -76,16 +76,17 @@ 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) + data = np.random.randn(30, 30) fig, axs = plt.subplots(1, 2, figsize=(6, 3), constrained_layout=True) - for [ax, cm] in zip(axs, cms): - psm = ax.pcolormesh(data, cmap=cm, rasterized=True, vmin=-4, vmax=4) + 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() @@ -145,6 +146,7 @@ def plot_examples(cms): [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)) @@ -170,9 +172,9 @@ def plot_linearmap(cdict): # are both superfluous to the interpolation, which happens between the last # element of the first anchor and the first element of the second anchor. -cdict['red'] = [[0.0, 0.0, 0.3], - [0.5, 1.0, 0.9], - [1.0, 1.0, 1.0]] +cdict['red'] = [[0.0, 0.0, 0.3], + [0.5, 1.0, 0.9], + [1.0, 1.0, 1.0]] plot_linearmap(cdict) From d6a5179c88a9307bdb4327f32ac02d13c57ad6df Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Wed, 22 Aug 2018 19:58:55 -0700 Subject: [PATCH 4/6] DOC: fix overinterp issue and modify intro para --- tutorials/colors/colormap-manipulation.py | 24 +++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index 466a6bc06d3c..114bb8be3272 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -3,15 +3,12 @@ Creating Colormaps in Matplotlib ******************************** -Matplotlib colormaps are implimented as a class, which makes them quite -flexible, but opaque to users as to how to create and/or -manipulate them. This opacity is not helped in the library by the fact that -the named colormaps are accessed via `.matplotlib.cm.get_cmap` module, whereas -the colormap class itself is defined in `.matplotlib.colors.Colormap`! - -Fortunately, the way to create colormaps is quite straight forward, by creating -an instance of class `.ListedColormap` using a Nx4 numpy array of values -between 0 and 1 to represent the RGBA values of the colormap. +Creating and manipulating colormaps in Matplotlib is quite straight-forward +using the class `.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` class that allows colormaps to be +specified with far fewer anchor points defining segments, and linearly +interpolating between the anchor points. Getting colormaps and accessing their values ============================================ @@ -93,11 +90,12 @@ def plot_examples(cms): plot_examples([viridis, newcmp]) ############################################################################## -# We can easily reduce the range of a colormap; here we choose the middle -# 0.5 of the colormap. +# 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. -viridis = cm.get_cmap('viridis', 256) -newcmp = ListedColormap(viridis(np.linspace(0.25, 0.75, 256))) +viridisBig = cm.get_cmap('viridis', 512) +newcmp = ListedColormap(viridisBig(np.linspace(0.25, 0.75, 256))) plot_examples([viridis, newcmp]) ############################################################################## From c6544d8a70305a20d63b86060a1b2eadc83ee5bd Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Wed, 22 Aug 2018 23:04:19 -0400 Subject: [PATCH 5/6] DOC: minor wording change --- tutorials/colors/colormap-manipulation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index 114bb8be3272..3716c71be969 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -3,7 +3,7 @@ Creating Colormaps in Matplotlib ******************************** -Creating and manipulating colormaps in Matplotlib is quite straight-forward +Creating and manipulating colormaps in Matplotlib is straight-forward using the class `.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` class that allows colormaps to be From e9cda7fbfb1d25552dc3282058042585b2b6291e Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Fri, 24 Aug 2018 15:32:10 -0700 Subject: [PATCH 6/6] DOC: try better math --- lib/matplotlib/cm.py | 20 +++++++--- tutorials/colors/colormap-manipulation.py | 47 +++++++++++++++-------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py index f5c60685e333..0dd3c9852eed 100644 --- a/lib/matplotlib/cm.py +++ b/lib/matplotlib/cm.py @@ -1,12 +1,20 @@ """ Builtin colormaps, colormap handling utilities, and the `ScalarMappable` mixin. - - See :doc:`/gallery/color/colormap_reference` for a list of builtin - colormaps. - - See :doc:`/tutorials/colors/colormaps` for an in-depth discussion of - choosing colormaps. - - See :doc:`/tutorials/colors/colormap-manipulation` for an in-depth - discussion of how to manipulate colormaps. +.. seealso:: + + :doc:`/gallery/color/colormap_reference` for a list of builtin + colormaps. + + :doc:`/tutorials/colors/colormap-manipulation` for examples of how to + make colormaps and + + :doc:`/tutorials/colors/colormaps` an in-depth discussion of + choosing colormaps. + + :doc:`/tutorials/colors/colormapnorms` for more details about data + normalization + """ diff --git a/tutorials/colors/colormap-manipulation.py b/tutorials/colors/colormap-manipulation.py index 3716c71be969..3c732f4f7ff7 100644 --- a/tutorials/colors/colormap-manipulation.py +++ b/tutorials/colors/colormap-manipulation.py @@ -55,8 +55,8 @@ print('viridis(np.linspace(0, 1, 15))', viridis(np.linspace(0, 1, 15))) ############################################################################## -# Creating a new ListedColormap -# ============================= +# 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, @@ -123,15 +123,19 @@ def plot_examples(cms): plot_examples([viridis, newcmp]) ############################################################################## -# LinearSegmented colormaps -# ========================= +# Creating linear segmented colormaps +# =================================== +# +# `.LinearSegmentedColormap` class specifies colormaps using anchor points +# between which RGB(A) values are interpolated. # -# `.LinearSegmentedColormap` have an alternate way to specify colormaps that -# specify anchor points for linear ramps for each of RGB, and optionally, alpha -# (RGBA). +# 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. # -# The format to specify these colormaps is a bit complicated to allow -# discontinuities at the anchor points. First, with no discontinuities: +# If there are no discontinuities, then ``yleft[i]=yright[i]``: cdict = {'red': [[0.0, 0.0, 0.0], [0.5, 1.0, 1.0], @@ -161,14 +165,23 @@ def plot_linearmap(cdict): plot_linearmap(cdict) ############################################################################# -# However, consider the case where the third column is different than the -# second. The linear interpolation between red[i, 0] and red[i+1, 0] is -# from red[i, 2] to red[i+1, 1]. This format allows us to have -# discontinuities in the colormap at the anchor points; in this case -# between 0 and 0.5, the linear interpolation 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, which happens between the last -# element of the first anchor and the first element of the second anchor. +# 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:: +# +# 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 discontiuity 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. cdict['red'] = [[0.0, 0.0, 0.3], [0.5, 1.0, 0.9],