我正在研究带有matplotlib的轮廓图,对于我的数据,我有一个区域,我有一个强大的渐变 - 现在我有一个问题,matplotlib会根据所选的色彩图显示不同颜色的区域,并分发整个光谱的线性颜色。
由于我的数据点的90%都在光谱的一端,并且只有这个小区域的行为完全不同,我的等值线图看起来很像
单色,如附图
另外,我添加了一些轮廓,以使值的差异更加明显。由于我们在特定的位置有一个巨大的渐变,因此有很多轮廓,很难看到底层的颜色或值。
有一个很好的方法如何使用matplotlib处理这些“有问题”的区域?也许在那里定义另一个色彩图?我试图设置一些手动级别并“删除”特定区域,但是找到一种方法来显示该区域的值
只是为了感受一下:我显示的最小值大约是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')
答案 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')