合并matplotlib中的颜色图 [英] Merge colormaps in matplotlib

查看:68
本文介绍了合并matplotlib中的颜色图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想合并两个颜色图以显示图像.我想在 -0.4 到 0.4 的范围内使用RdBu",然后从 0.4 到最大值(例如 1.5)我想使用从相同蓝色到另一种颜色(例如绿色)的渐变.

我该怎么做?

这是我到目前为止所走的距离:

将 numpy 导入为 np导入matplotlib.pyplot作为plt导入 matplotlib.colors 作为颜色从matplotlib.mlab导入bivariate_normalN = 100'''自定义规范:具有自定义规范化的示例.这个使用上面的例子,并以不同的方式对负数据进行归一化从积极.'''X,Y = np.mgrid [-3:3:complex(0,N),-2:2:complex(0,N)]Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2Z1 = Z1/0.03#制定自己的规范的示例.另请参阅 matplotlib.colors.# 来自 Joe Kington:这个给出了两种不同的线性斜坡:类 MidpointNormalize(colors.Normalize):def __init __(self,vmin = None,vmax = None,midpoint = None,clip = False):self.midpoint =中点color.Normalize.__init__(self, vmin, vmax, clip)def __call __(自身,值,剪辑=无):#我忽略了蒙版值和各种边缘情况,# 简单的例子...x,y = [self.vmin,self.midpoint,self.vmax],[0,0.5,1]返回 np.ma.masked_array(np.interp(value, x, y))无花果,ax = plt.subplots(1,1)minValue = Z1.min()最大值 = 0.4pcm = ax.imshow(Z1,norm = MidpointNormalize(midpoint = 0.),vmin = minValue,vmax = maxValue,cmap ='RdBu',origin ='lower',方面=1.0,插值='无')cbar = fig.colorbar(pcm, ax=ax, extend='both', ticks=[minValue, 0.0, maxValue])fig.tight_layout()plt.show()

解决方案

目的是创建一个颜色映射,它有几个预定义的值.颜色图的开始应在 vmin 处,白色(在"RdBu"颜色图的中间)应在 0 处,即另一个预定义点( 0.4) 应该是 RdBu 颜色图的上端,然后颜色应该向某个结束颜色渐变.

为此,我们需要两件事.(a)包含所有这些颜色的颜色图和(b)允许将中间点映射到相应颜色的规范化.

(a) 创建颜色图

颜色图的范围是0到1.我们可以创建颜色图,以使"RdBu"颜色图的颜色扩展到所需颜色图的前半部分,例如0为红色,0.25为白色,0.5为蓝色.颜色图的后半部分范围从 0.5(相同的蓝色)到 0.75 的中间绿松石到 1 的绿色.(选择中间绿松石是因为从蓝色到绿色的直接过渡会导致中间有些模糊的棕蓝色,这可能是不受欢迎的.)这些步骤是通过以下代码完成的

  colors = plt.cm.RdBu(np.linspace(0,1.,128))颜色= zip(np.linspace(0,0.5,128),颜色)颜色+ = [(0.75,#1fa187"),(1.,#76d154")]cmap = matplotlib.colors.LinearSegmentedColormap.from_list('mycmap', 颜色)

使 cmap 是所需的颜色图.

(b)创建规范化

I want to merge two colormaps for an imshow plot. I want to use 'RdBu' for the range -0.4 to 0.4, then from 0.4 to the maximum value (say 1.5) I want to use a gradient from the same blue to another color (say green for example).

How can I do that?

This is how far I got so far:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal

N = 100
'''
Custom Norm: An example with a customized normalization.  This one
uses the example above, and normalizes the negative data differently
from the positive.
'''
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2  \
    - 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03

# Example of making your own norm.  Also see matplotlib.colors.
# From Joe Kington: This one gives two different linear ramps:

class MidpointNormalize(colors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        # I'm ignoring masked values and all kinds of edge cases to make a
        # simple example...
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(value, x, y))

fig, ax = plt.subplots(1, 1)

minValue = Z1.min()
maxValue = 0.4

pcm = ax.imshow(Z1,
                norm=MidpointNormalize(midpoint=0.),
                vmin=minValue, vmax=maxValue,
                cmap='RdBu',
                origin='lower',
                aspect=1.0,
                interpolation='none')
cbar = fig.colorbar(pcm, ax=ax, extend='both', ticks=[minValue, 0.0, maxValue])

fig.tight_layout()

plt.show()

解决方案

The purpose is to create a colormapping, which has several predefined values. The start of colormap should be at vmin, white (which is in the middle of the "RdBu" colormap) should be at 0, another predefined point (0.4) shall be the upper end of the RdBu colormap and then the color shall fade towards some end color.

For this purpose we need two things. (a) a colormap that has all those colors in it and (b) a Normalization that allows to map the intermediate points to the respective colors.

(a) Creating the colormap

Colormaps range between 0 and 1. We may create the colormap such that the colors from the "RdBu" colormap extend over the first half of the desired colormap, such that 0 is red, 0.25 is white and 0.5 is blue. The second half of the colormap then ranges from 0.5 (the same blue) over some intermediate turquoise at 0.75 to green at 1. (The intermediate turquoise is chosen because a direct transition from blue to green would result in some smeared brownish blue in the middle, which is probably undesired.) Those steps are accomplished via the following code

colors = plt.cm.RdBu(np.linspace(0,1.,128)) 
colors = zip(np.linspace(0,0.5,128),colors) 
colors += [ (0.75,"#1fa187"),(1., "#76d154")] 
cmap = matplotlib.colors.LinearSegmentedColormap.from_list('mycmap', colors)

such that cmap is the desired colormap.

(b) Creating the normalization

Unlike the MidpointNormalization, which has one intermediate point, we now need two intermediate points: one being the white color at 0 value and one being the end of the first half of the colormap. We can hence use two values in the custom normalization (here called low and up), such the interpolation ranges over 4 points in total and low corresponds to the 0.25 value of the colormap and up corresponds to the 0.5 value.

x, y = [self.vmin, self.low, self.up, self.vmax], [0, 0.25, 0.5, 1]

Complete code:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors
from matplotlib.mlab import bivariate_normal

N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2  \
    - 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03


class TwoInnerPointsNormalize(matplotlib.colors.Normalize):
    def __init__(self, vmin=None, vmax=None, low=None, up=None, clip=False):
        self.low = low
        self.up = up
        matplotlib.colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.low, self.up, self.vmax], [0, 0.25, 0.5, 1]
        return np.ma.masked_array(np.interp(value, x, y))

colors = plt.cm.RdBu(np.linspace(0,1.,128)) 
colors = zip(np.linspace(0,0.5,128),colors) 
colors += [ (0.75,"#1fa187"),(1., "#76d154")] 
cmap = matplotlib.colors.LinearSegmentedColormap.from_list('mycmap', colors)


fig, ax = plt.subplots(1, 1)

norm = TwoInnerPointsNormalize(vmin=-0.4, vmax=1.5, low=0., up=0.4)
pcm = ax.imshow(Z1, norm=norm, cmap=cmap,
                origin='lower', aspect=1.0, interpolation='none')
cbar = fig.colorbar(pcm, ax=ax, ticks=[-0.4,0.0, 0.4,1.5]) 

fig.tight_layout()
plt.show()

这篇关于合并matplotlib中的颜色图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆