参考 https://matplotlib.org/stable/tutorials/colors/colormap-manipulation.html 

是关于如何创建Colormap的示例代码,我的理解都写注释上了。

先介绍如何创建ListedColormap,再介绍如何创建 LinearSegmentedColormap(没看懂怎么弄的)

可以在代码中添加一些input()来分部分看。

"""
********************************
Creating Colormaps in Matplotlib
********************************

Matplotlib has a number of built-in colormaps accessible via
`.matplotlib.colormaps`.  There are also external libraries like
palettable_ that have many extra colormaps.

.. _palettable: https://jiffyclub.github.io/palettable/

However, we often want to create or manipulate colormaps in Matplotlib.
This can be done using the class `.ListedColormap` or
`.LinearSegmentedColormap`.
Seen from the outside, both colormap classes map values between 0 and 1 to
a bunch of colors. There are, however, slight differences, some of which are
shown in the following.

Before manually creating or manipulating colormaps, let us first see how we
can obtain colormaps and their colors from existing colormap classes.


Getting colormaps and accessing their values
============================================

First, getting a named colormap, most of which are listed in
:doc:`/tutorials/colors/colormaps`, may be done using `.matplotlib.colormaps`,
which returns a colormap object.  The length of the list of colors used
internally to define the colormap can be adjusted via `.Colormap.resampled`.
Below we use a modest value of 8 so there are not a lot of values to look at.

"""

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.colors import ListedColormap, LinearSegmentedColormap


# 由库里面有的viridis重新采样得到自己的
newviridis = mpl.colormaps['viridis'].resampled(8)

##############################################################################
# The object ``viridis`` is a callable, that when passed a float between
# 0 and 1 returns an RGBA value from the colormap:
print(newviridis(0.56))

##############################################################################
# ListedColormap
# --------------
#
# `.ListedColormap`\s store their color values in a ``.colors`` attribute.
# 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.

print('viridis.colors', newviridis.colors)
# 查看颜色的值,是一个浮点数列表
# print("range(8)", range(8), "np.linspace(0, 1, 8)", np.linspace(0, 1, 8))

print('viridis(range(8))', newviridis(range(8)))
print('viridis(np.linspace(0, 1, 8))', newviridis(np.linspace(0, 1, 8)))

##############################################################################
# The colormap is a lookup table, so "oversampling" the colormap returns
# nearest-neighbor interpolation (note the repeated colors in the list below)
# 采样一般是8份,如果过采样了,则会采样最邻近的值,有重复的采样值。
print('viridis(np.linspace(0, 1, 12))', newviridis(np.linspace(0, 1, 12)))

##############################################################################
# LinearSegmentedColormap
# -----------------------
# `.LinearSegmentedColormap`\s do not have a ``.colors`` attribute.
# However, one may still call the colormap with an integer array, or with a
# float array between 0 and 1.

mycopper = mpl.colormaps['copper'].resampled(8)

print('mycopper(range(8))', mycopper(range(8)))
print('mycopper(np.linspace(0, 1, 8))', mycopper(np.linspace(0, 1, 8)))

##############################################################################
# Creating listed colormaps
# =========================
#
# Creating a colormap is essentially the inverse operation of the above where
# we supply a list or array of color specifications to `.ListedColormap` to
# make a new colormap.
#
# Before continuing with the tutorial, let us define a helper function that
# takes one of more colormaps as input, creates some random data and applies
# the colormap(s) to an image plot of that dataset.


def plot_examples(colormaps):
    """
    Helper function to plot data with associated colormap.
    """
    np.random.seed(19680801)
    data = np.random.randn(30, 30)
    # 产生范围为0到30的随机数,变成一个正方形的形状,里面有30*30个随机数值,然后随机数值对应色带上的颜色。
    # 用于演示各种颜色占总色带的比例
    n = len(colormaps)
    fig, axs = plt.subplots(1, n, figsize=(n * 2 + 2, 3),
                            constrained_layout=True, squeeze=False)
    for [ax, cmap] in zip(axs.flat, colormaps):
        psm = ax.pcolormesh(data, cmap=cmap, rasterized=True, vmin=-4, vmax=4)
        fig.colorbar(psm, ax=ax)
    plt.show()
# 创建了一个函数来演示自定义ListedColormap的效果

##############################################################################
# In the simplest case we might type in a list of color names to create a
# colormap from those.
# "darkorange", "gold", "cyan", "lightseagreen"都是库颜色
cmap = ListedColormap(["darkorange", "gold", "cyan", "lightseagreen"])
plot_examples([cmap])

##############################################################################
# In fact, that list may contain any valid
# :doc:`Matplotlib color specification </tutorials/colors/colors>`.
# Particularly useful for creating custom colormaps are Nx4 numpy arrays.
# Because with the variety of numpy operations that we can do on a such an
# array, carpentry of new colormaps from existing colormaps become quite
# straight forward.
#
# For example, suppose we want to make the first 25 entries of a 256-length
# "viridis" colormap pink for some reason:

# 对库里的viridis重新采样为256份,增加一个粉红颜色
viridis = mpl.colormaps['viridis'].resampled(256)
newcolors = viridis(np.linspace(0, 1, 256))
pink = np.array([248/256, 24/256, 148/256, 1])
newcolors[:25, :] = pink
# 粉红占25/256
newcmp = ListedColormap(newcolors)

plot_examples([viridis, newcmp])

##############################################################################
# We can reduce the dynamic range of a colormap; here we choose the
# middle half of the colormap.  Note, however, that because viridis is a
# listed colormap, we will end up with 128 discrete values instead of the 256
# values that were in the original colormap. This method does not interpolate
# in color-space to add new colors.

# 可以截取库函数色带的一部分,这里是截取viridis_big的1/4到3/4
viridis_big = mpl.colormaps['viridis']
newcmp = ListedColormap(viridis_big(np.linspace(0.25, 0.75, 128)))
plot_examples([viridis, newcmp])

##############################################################################
# and we can easily concatenate two colormaps:
# 合并两种颜色形成一个新的ListedColormap
top = mpl.colormaps['Oranges_r'].resampled(128)
bottom = mpl.colormaps['Blues'].resampled(128)

newcolors = np.vstack((top(np.linspace(0, 1, 128)),
                       bottom(np.linspace(0, 1, 128))))
newcmp = ListedColormap(newcolors, name='OrangeBlue')

plot_examples([top, bottom])
# 合并之前的倆颜色
plot_examples([viridis, newcmp])
# viridis颜色和合并之后的两颜色


##############################################################################
# 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 colormap that
# goes from brown (RGB: 90, 40, 40) to white (RGB: 255, 255, 255).
# 棕色到白色的变换,因为白色是1,只需要很自然的划分棕色的RGB各个分量,比如由90/256到1, 就行了
N = 256
vals = np.ones((N, 4))
print(vals, type(vals), len(vals), len(vals[0]))
vals[:, 0] = np.linspace(90/256, 1, N)
vals[:, 1] = np.linspace(40/256, 1, N)
vals[:, 2] = np.linspace(40/256, 1, N)
print(vals)
newcmp = ListedColormap(vals)
plot_examples([viridis, newcmp])
##############################################################################
# Creating linear segmented colormaps
# ===================================
#
# The `.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]``:

# 自定义linearmap
# cdict的red有三行,第一行对应的是0, 0 这个点,第二行对应的是0.5, 1这个点,第三行是1, 1这个点,用red把这三个点依次连起来
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)
#
#############################################################################
# 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 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]`` (i.e., ``yleft[0]``)
# is the value to the left of 0, and ``red[2, 2]`` (i.e., ``yright[2]``) is the
# value to the right of 1, which are outside the color mapping domain.

# 更改了,第一行对应的是0, 0.3 这个点,第二行是连接(0.5, 1),(0.5,0.9) 第三行是1, 1这个点,用red把这三个点依次连起来
# yleft[i]  yright[i]相等时表明是一个点,不相等时,表示两个点连起来。如下所示
cdict['red'] = [[0.0,  0.0, 0.3],
                [0.5,  1.0, 0.9],
                [1.0,  1.0, 1.0]]
plot_linearmap(cdict)

#############################################################################
# Directly creating a segmented colormap from a list
# --------------------------------------------------
#
# The approach described above is very versatile, but admittedly a bit
# cumbersome to implement. For some basic cases, the use of
# `.LinearSegmentedColormap.from_list` may be easier. This creates a segmented
# colormap with equal spacings from a supplied list of colors.

# 用比较简单的方式,直接拼接库里的元素创建LinearSegmentedColormap
colors = ["darkorange", "gold", "lawngreen", "lightseagreen"]
cmap1 = LinearSegmentedColormap.from_list("mycmap", colors)

#############################################################################
# If desired, the nodes of the colormap can be given as numbers between 0 and
# 1. For example, one could have the reddish part take more space in the
# colormap.

nodes = [0.0, 0.4, 0.8, 1.0]
cmap2 = LinearSegmentedColormap.from_list("mycmap", list(zip(nodes, colors)))

plot_examples([cmap1, cmap2])

#############################################################################
#
# .. admonition:: References
#
#    The use of the following functions, methods, classes and modules is shown
#    in this example:
#
#    - `matplotlib.axes.Axes.pcolormesh`
#    - `matplotlib.figure.Figure.colorbar`
#    - `matplotlib.colors`
#    - `matplotlib.colors.LinearSegmentedColormap`
#    - `matplotlib.colors.ListedColormap`
#    - `matplotlib.cm`
#    - `matplotlib.colormaps`