{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Create a colormap from a list of colors\n\nFor more detail on creating and manipulating colormaps see\n`colormap-manipulation`.\n\nCreating a `colormap ` from a list of colors\ncan be done with the `.LinearSegmentedColormap.from_list` method. You must\npass a list of RGB tuples that define the mixture of colors from 0 to 1.\n\n\n## Creating custom colormaps\nIt is also possible to create a custom mapping for a colormap. This is\naccomplished by creating dictionary that specifies how the RGB channels\nchange from one end of the cmap to the other.\n\nExample: suppose you want red to increase from 0 to 1 over the bottom\nhalf, green to do the same over the middle half, and blue over the top\nhalf. Then you would use::\n\n cdict = {\n 'red': (\n (0.0, 0.0, 0.0),\n (0.5, 1.0, 1.0),\n (1.0, 1.0, 1.0),\n ),\n 'green': (\n (0.0, 0.0, 0.0),\n (0.25, 0.0, 0.0),\n (0.75, 1.0, 1.0),\n (1.0, 1.0, 1.0),\n ),\n 'blue': (\n (0.0, 0.0, 0.0),\n (0.5, 0.0, 0.0),\n (1.0, 1.0, 1.0),\n )\n }\n\nIf, as in this example, there are no discontinuities in the r, g, and b\ncomponents, then it is quite simple: the second and third element of\neach tuple, above, is the same -- call it \"``y``\". The first element (\"``x``\")\ndefines interpolation intervals over the full range of 0 to 1, and it\nmust span that whole range. In other words, the values of ``x`` divide the\n0-to-1 range into a set of segments, and ``y`` gives the end-point color\nvalues for each segment.\n\nNow consider the green, ``cdict['green']`` is saying that for:\n\n- 0 <= ``x`` <= 0.25, ``y`` is zero; no green.\n- 0.25 < ``x`` <= 0.75, ``y`` varies linearly from 0 to 1.\n- 0.75 < ``x`` <= 1, ``y`` remains at 1, full green.\n\nIf there are discontinuities, then it is a little more complicated. Label the 3\nelements in each row in the ``cdict`` entry for a given color as ``(x, y0,\ny1)``. Then for values of ``x`` between ``x[i]`` and ``x[i+1]`` the color value\nis interpolated between ``y1[i]`` and ``y0[i+1]``.\n\nGoing back to a cookbook example::\n\n cdict = {\n 'red': (\n (0.0, 0.0, 0.0),\n (0.5, 1.0, 0.7),\n (1.0, 1.0, 1.0),\n ),\n 'green': (\n (0.0, 0.0, 0.0),\n (0.5, 1.0, 0.0),\n (1.0, 1.0, 1.0),\n ),\n 'blue': (\n (0.0, 0.0, 0.0),\n (0.5, 0.0, 0.0),\n (1.0, 1.0, 1.0),\n )\n }\n\nand look at ``cdict['red'][1]``; because ``y0 != y1``, it is saying that for\n``x`` from 0 to 0.5, red increases from 0 to 1, but then it jumps down, so that\nfor ``x`` from 0.5 to 1, red increases from 0.7 to 1. Green ramps from 0 to 1\nas ``x`` goes from 0 to 0.5, then jumps back to 0, and ramps back to 1 as ``x``\ngoes from 0.5 to 1. ::\n\n row i: x y0 y1\n /\n /\n row i+1: x y0 y1\n\nAbove is an attempt to show that for ``x`` in the range ``x[i]`` to ``x[i+1]``,\nthe interpolation is between ``y1[i]`` and ``y0[i+1]``. So, ``y0[0]`` and\n``y1[-1]`` are never used.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nimport matplotlib as mpl\nfrom matplotlib.colors import LinearSegmentedColormap\n\n# Make some illustrative fake data:\n\nx = np.arange(0, np.pi, 0.1)\ny = np.arange(0, 2 * np.pi, 0.1)\nX, Y = np.meshgrid(x, y)\nZ = np.cos(X) * np.sin(Y) * 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Colormaps from a list\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "colors = [(1, 0, 0), (0, 1, 0), (0, 0, 1)] # R -> G -> B\nn_bins = [3, 6, 10, 100] # Discretizes the interpolation into bins\ncmap_name = 'my_list'\nfig, axs = plt.subplots(2, 2, figsize=(6, 9))\nfig.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05)\nfor n_bin, ax in zip(n_bins, axs.flat):\n # Create the colormap\n cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N=n_bin)\n # Fewer bins will result in \"coarser\" colomap interpolation\n im = ax.imshow(Z, origin='lower', cmap=cmap)\n ax.set_title(\"N bins: %s\" % n_bin)\n fig.colorbar(im, ax=ax)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Custom colormaps\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "cdict1 = {\n 'red': (\n (0.0, 0.0, 0.0),\n (0.5, 0.0, 0.1),\n (1.0, 1.0, 1.0),\n ),\n 'green': (\n (0.0, 0.0, 0.0),\n (1.0, 0.0, 0.0),\n ),\n 'blue': (\n (0.0, 0.0, 1.0),\n (0.5, 0.1, 0.0),\n (1.0, 0.0, 0.0),\n )\n}\n\ncdict2 = {\n 'red': (\n (0.0, 0.0, 0.0),\n (0.5, 0.0, 1.0),\n (1.0, 0.1, 1.0),\n ),\n 'green': (\n (0.0, 0.0, 0.0),\n (1.0, 0.0, 0.0),\n ),\n 'blue': (\n (0.0, 0.0, 0.1),\n (0.5, 1.0, 0.0),\n (1.0, 0.0, 0.0),\n )\n}\n\ncdict3 = {\n 'red': (\n (0.0, 0.0, 0.0),\n (0.25, 0.0, 0.0),\n (0.5, 0.8, 1.0),\n (0.75, 1.0, 1.0),\n (1.0, 0.4, 1.0),\n ),\n 'green': (\n (0.0, 0.0, 0.0),\n (0.25, 0.0, 0.0),\n (0.5, 0.9, 0.9),\n (0.75, 0.0, 0.0),\n (1.0, 0.0, 0.0),\n ),\n 'blue': (\n (0.0, 0.0, 0.4),\n (0.25, 1.0, 1.0),\n (0.5, 1.0, 0.8),\n (0.75, 0.0, 0.0),\n (1.0, 0.0, 0.0),\n )\n}\n\n# Make a modified version of cdict3 with some transparency\n# in the middle of the range.\ncdict4 = {\n **cdict3,\n 'alpha': (\n (0.0, 1.0, 1.0),\n # (0.25, 1.0, 1.0),\n (0.5, 0.3, 0.3),\n # (0.75, 1.0, 1.0),\n (1.0, 1.0, 1.0),\n ),\n}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we will use this example to illustrate 2 ways of\nhandling custom colormaps.\nFirst, the most direct and explicit:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "blue_red1 = LinearSegmentedColormap('BlueRed1', cdict1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Second, create the map explicitly and register it.\nLike the first method, this method works with any kind\nof Colormap, not just\na LinearSegmentedColormap:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "mpl.colormaps.register(LinearSegmentedColormap('BlueRed2', cdict2))\nmpl.colormaps.register(LinearSegmentedColormap('BlueRed3', cdict3))\nmpl.colormaps.register(LinearSegmentedColormap('BlueRedAlpha', cdict4))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make the figure, with 4 subplots:\n\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, axs = plt.subplots(2, 2, figsize=(6, 9))\nfig.subplots_adjust(left=0.02, bottom=0.06, right=0.95, top=0.94, wspace=0.05)\n\nim1 = axs[0, 0].imshow(Z, cmap=blue_red1)\nfig.colorbar(im1, ax=axs[0, 0])\n\nim2 = axs[1, 0].imshow(Z, cmap='BlueRed2')\nfig.colorbar(im2, ax=axs[1, 0])\n\n# Now we will set the third cmap as the default. One would\n# not normally do this in the middle of a script like this;\n# it is done here just to illustrate the method.\n\nplt.rcParams['image.cmap'] = 'BlueRed3'\n\nim3 = axs[0, 1].imshow(Z)\nfig.colorbar(im3, ax=axs[0, 1])\naxs[0, 1].set_title(\"Alpha = 1\")\n\n# Or as yet another variation, we can replace the rcParams\n# specification *before* the imshow with the following *after*\n# imshow.\n# This sets the new default *and* sets the colormap of the last\n# image-like item plotted via pyplot, if any.\n#\n\n# Draw a line with low zorder so it will be behind the image.\naxs[1, 1].plot([0, 10 * np.pi], [0, 20 * np.pi], color='c', lw=20, zorder=-1)\n\nim4 = axs[1, 1].imshow(Z)\nfig.colorbar(im4, ax=axs[1, 1])\n\n# Here it is: changing the colormap for the current image and its\n# colorbar after they have been plotted.\nim4.set_cmap('BlueRedAlpha')\naxs[1, 1].set_title(\"Varying alpha\")\n\nfig.suptitle('Custom Blue-Red colormaps', fontsize=16)\nfig.subplots_adjust(top=0.9)\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. admonition:: References\n\n The use of the following functions, methods, classes and modules is shown\n in this example:\n\n - `matplotlib.axes.Axes.imshow` / `matplotlib.pyplot.imshow`\n - `matplotlib.figure.Figure.colorbar` / `matplotlib.pyplot.colorbar`\n - `matplotlib.colors`\n - `matplotlib.colors.LinearSegmentedColormap`\n - `matplotlib.colors.LinearSegmentedColormap.from_list`\n - `matplotlib.cm`\n - `matplotlib.cm.ScalarMappable.set_cmap`\n - `matplotlib.cm.ColormapRegistry.register`\n\n.. tags::\n\n styling: colormap\n plot-type: imshow\n level: intermediate\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }