如何修改我的等值线图以更好地显示具有大梯度的区域?

时间:2017-07-05 13:44:59

标签: python matplotlib

我正在研究带有matplotlib的轮廓图,对于我的数据,我有一个区域,我有一个强大的渐变 - 现在我有一个问题,matplotlib会根据所选的色彩图显示不同颜色的区域,并分发整个光谱的线性颜色。

由于我的数据点的90%都在光谱的一端,并且只有这个小区域的行为完全不同,我的等值线图看起来很像 单色,如附图enter image description here

所示

另外,我添加了一些轮廓,以使值的差异更加明显。由于我们在特定的位置有一个巨大的渐变,因此有很多轮廓,很难看到底层的颜色或值。

有一个很好的方法如何使用matplotlib处理这些“有问题”的区域?也许在那里定义另一个色彩图?我试图设置一些手动级别并“删除”特定区域,但是找到一种方法来显示该区域的值modified scale

只是为了感受一下:我显示的最小值大约是7,最大值是145和平均值

以下是我的代码的重要部分:

z = [] # z is a list of values that i've read in before from a file
X = np.arange(0, 61, 1)
Y = np.arange(0, 151, 1)
z = z.reshape((len(Y), len(X)))
blurred = gaussian_filter(z, sigma=2) # applies a gaussian filter to smooth the plot
xx, yy = np.meshgrid(X, Y) # gets the grid for the plot

procent = np.arange(np.min(z), np.max(z), 5) # levels for the contourlines
newlevels = [5,10,15,20,30,40,50, 80, 100, 120, 140] # sets manual levels for the plot, where I've tried to set a stronger focus on the first part of the spectra
plusmin = plt.contourf(xx,yy,z, origin='lower', extend='both', levels=procent,)
levels = np.arange(np.min(z), np.max(z), 3)

CS = plt.contourf(xx, yy, z, levels=newlevels, extend="both", cmap=cm.viridis)
s = plt.contour(xx, yy, blurred, plusmin.levels, colors='white', linewidths=2)
cbar = plt.colorbar(CS, fraction=0.042, pad=0.04)
ax.clabel(s, fontsize=12, inline=1, colors ='white')

1 个答案:

答案 0 :(得分:0)

解决方案可能是缩放色彩图,以便平均显示每种颜色。

这是我用来处理这类问题的一段代码。使用matplotlib肯定有更多正确的方法,但我不知道。

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

#-----------------------
def repartition(z):
    """compute the repartition function of an array"""
    hist, bin_edges = np.histogram(z.flat[:], bins = 1000)
    x = 0.5 * (bin_edges[1:] + bin_edges[:-1])
    y = np.cumsum(np.array(hist, float))
    y = (y - y[0]) / (y[-1] - y[0])
    return x, y

#-----------------------
def adjustcmap2data(Z, cmap, N = 16384):
    """scale the colormap so that all colors are equally displayed"""
    def cmap2xs(cmap):
        "convert cmap to matrix"
        sd = cmap._segmentdata
        xr = [tup[0] for tup in sd['red']]
        xg = [tup[0] for tup in sd['green']]
        xb = [tup[0] for tup in sd['blue']]
        return tuple([np.array(x) for x in xr, xg, xb])

    def xs2cmap(cmap, xr, xg, xb):
        "convert matrix to cmap"
        sd = cmap._segmentdata
        for k in 'red', 'green', 'blue':
            sd[k] = list(sd[k])
            for i in xrange(len(sd[k])): sd[k][i] = list(sd[k][i])
        for i in xrange(len(sd['red'])):   sd['red'][i]    = (xr[i], sd['red'][i][1], sd['red'][i][2])
        for i in xrange(len(sd['green'])): sd['green'][i]  = (xg[i], sd['green'][i][1], sd['green'][i][2])
        for i in xrange(len(sd['blue'])):  sd['blue'][i]   = (xb[i], sd['blue'][i][1], sd['blue'][i][2])
        for k in 'red', 'green', 'blue':
            sd[k] = tuple(sd[k])
        return colors.LinearSegmentedColormap('mycmap_%010.0f' % (np.random.randn() * 1.e10), sd, N)

    x, y = repartition(Z)
    x = (x - x[0]) / (x[-1] - x[0])
    xr, xg, xb = cmap2xs(cmap)
    xrr = np.interp(xr, xp = y, fp = x)
    xgg = np.interp(xg, xp = y, fp = x)
    xbb = np.interp(xb, xp = y, fp = x)
    for x in xrr, xgg, xbb:
        x[x < 0.] = 0.
        x[x > 1.] = 1.
        x[0], x[-1] = 0.,  1.
        x.sort()
    mycmap = xs2cmap(copy.deepcopy(cmap), xrr, xgg, xbb)
    return mycmap


#---------------------
def fake_data():
    """generate a fake dataset"""
    x = np.linspace(-1., 1., 256)
    y = np.linspace(-1., 1., 256)
    X, Y = np.meshgrid(x, y)
    Z = np.zeros_like(X)
    #create background noise
    for _ in xrange(100):
        x0 = np.random.randn() 
        y0 = np.random.randn()
        Z += 0.05 * np.exp(-0.5 * (((X - x0) / 0.1) ** 2. + ((Y - y0) / 0.1) ** 2.))
    #add strong peak
    Z += np.exp(-0.5 * (((X - 0.5) / 0.3) ** 2. + ((Y - 0.5) / 0.02) ** 2.))
    return X, Y, Z

#---------------------
if __name__ == "__main__":
    X, Y, Z = fake_data()
    plt.figure()
    cmap = plt.cm.spectral
    plt.pcolormesh(X, Y, Z, cmap = cmap)
    plt.colorbar()
    plt.contour(X, Y, Z, colors = "w")
    plt.gcf().show()

    plt.figure()
    scaledcmap = adjustcmap2data(Z, cmap = cmap)
    plt.pcolormesh(X, Y, Z, cmap = scaledcmap)
    plt.colorbar()
    plt.gcf().show()

    raw_input('pause')

哪个应该给你以下结果
1)线性色条 enter image description here 2)缩放颜色条 enter image description here