Matplotlib imshow - 在某些值范围内'加速'颜色变化

时间:2016-10-28 09:51:02

标签: python matplotlib imshow

我目前正在imshow中绘制x,y轴上的一些标签,但超过95%的点位于0-0.2范围内,而不到10%位于0.2-1.0范围内。使用默认的'jet'颜色图,这导致几乎所有的图都显示为蓝色,即使95%的数据存在差异,但在视觉上不可观察。

有没有办法告诉matplotlib,例如,颜色在0.0-0.1范围内变化的速率翻两番,并相应地缩放剩余的0.2-1.0范围?任何帮助将不胜感激。

提前致谢!

编辑:看到这只是一个直观的表示,我意识到我有一个选项是将0.2范围内的数据重新缩放到我认为合适的任何值,以便更改更明显,然后手动相应地创建颜色条。如果可能的话,我仍然希望能够让matplotlib的imshow本地化。

1 个答案:

答案 0 :(得分:1)

如果您想在图像图中强调数据中的小值,我永远不会更改实际数据本身。这可能会导致很多混乱。 相反,正如我在评论中所说,更改色彩映射。

这样做的方式记录在Matplotlib Color Normalization Tutorial以及SO上。特别是this article及其中的答案实际上说明了人们的可能性。

我在下面的示例中结合了两个概念来显示选项。

  • 一种方法是重新缩放色彩映射图,使最初位于色彩映射图中间(midpoint)的值向下移动。通过这种方式,0和新midpoint之间会添加更多变体,而上述所有内容都会被拉伸。人们可以将其视为拼接在一起的两个线性色图。
  • 另一种是简单地使用颜色的对数缩放。

这是示例代码

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.colors as colors


def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'):
    '''
    function taken from
    https://stackoverflow.com/questions/7404116/...
        ...defining-the-midpoint-of-a-colormap-in-matplotlib
    Function to offset the "center" of a colormap. Useful for
    data with a negative min and positive max and you want the
    middle of the colormap's dynamic range to be at zero

    Input
    -----
      cmap : The matplotlib colormap to be altered
      start : Offset from lowest point in the colormap's range.
          Defaults to 0.0 (no lower ofset). Should be between
          0.0 and `midpoint`.
      midpoint : The new center of the colormap. Defaults to 
          0.5 (no shift). Should be between 0.0 and 1.0. In
          general, this should be  1 - vmax/(vmax + abs(vmin))
          For example if your data range from -15.0 to +5.0 and
          you want the center of the colormap at 0.0, `midpoint`
          should be set to  1 - 5/(5 + 15)) or 0.75
      stop : Offset from highets point in the colormap's range.
          Defaults to 1.0 (no upper ofset). Should be between
          `midpoint` and 1.0.
    '''
    cdict = {  'red': [],  'green': [], 'blue': [],  'alpha': []  }

    # regular index to compute the colors
    reg_index = np.linspace(start, stop, 257)

    # shifted index to match the data
    shift_index = np.hstack([
        np.linspace(0.0, midpoint, 128, endpoint=False), 
        np.linspace(midpoint, 1.0, 129, endpoint=True)
    ])

    for ri, si in zip(reg_index, shift_index):
        r, g, b, a = cmap(ri)

        cdict['red'].append((si, r, r))
        cdict['green'].append((si, g, g))
        cdict['blue'].append((si, b, b))
        cdict['alpha'].append((si, a, a))

    newcmap = matplotlib.colors.LinearSegmentedColormap(name, cdict)
    plt.register_cmap(cmap=newcmap)

    return newcmap


x = np.linspace(-3, 3, num=601)
X,Y = np.meshgrid(x,x)
Z = np.sinc( (X*np.cos(1)+Y*np.sin(1))**2 +(-X*np.sin(1)+0.2*Y*np.cos(1))**2 )**2 

orig_cmap = matplotlib.cm.viridis 
shifted_cmap = shiftedColorMap(orig_cmap, midpoint=0.05, name='shifted')


fig = plt.figure(figsize=(4,9))
ax = [fig.add_subplot(3,1,n+1) for n in range(3)]

# normal cmap
im0 = ax[0].imshow(Z, interpolation="none", cmap=orig_cmap)
fig.colorbar(im0, ax=ax[0])
ax[0].set_title('Default behavior (hard to see small values)', fontsize=10)

#example using the custom shiftedColorMap function
#taken from https://stackoverflow.com/questions/7404116/defining-the-midpoint-of-a-colormap-in-matplotlib
im1 = ax[1].imshow(Z, interpolation="none", cmap=shifted_cmap)
fig.colorbar(im1, ax=ax[1])
ax[1].set_title('Center of colormap shifted to 0.05', fontsize=10)

#example using colors.LogNorm()
#taken from http://matplotlib.org/users/colormapnorms.html
im2 = ax[2].imshow(Z, interpolation="none", norm=colors.LogNorm(vmin=10e-5, vmax=Z.max()), cmap=orig_cmap)
fig.colorbar(im2, ax=ax[2])
ax[2].set_title('Logarithmically scaled Colormap', fontsize=10)

for axis in ax:
    axis.set_yticks([])
    axis.set_xticks([])
plt.tight_layout()    
plt.show() 
制造

enter image description here