我怎样才能在 matplotlib 中有直线轮廓线?

How can I have straight contourlines in matplotlib?

我正在用 imshow 绘制值,我希望在某个值处有一条等高线。但是,pyplot.contour() 使用某种插值,导致轮廓线围绕该点呈对角线。我怎样才能确保线条与我的矩形框完全对齐(所以只有水平线和垂直线)?

(谁要复制我得到的图,数值上传here)

数据图片如下所示:

使用此代码生成:

pyplot.imshow(KS_imshow, extent = [5. ,8., 0., 22., ], origin='lower', interpolation='nearest', aspect='auto', cmap = 'Blues', vmin = 0., vmax = 1.)
cbar = pyplot.colorbar()

CS2 = pyplot.contour(ri,phii,KS_imshow,levels=[0.5], colors='r')
cbar.add_lines(CS2)

pyplot.show()

变量 riphiiKS_imshow 在链接文档中。

问题是 imshow 创建了 "pixels",但基础数据只是点(在中心)。因此 contourimshow 创建的图像一无所知。但是,您可以通过放大原始数据然后在其上使用 contour 来创建类似的图像。这当然是一个黑客,但它实现了你想要的。但是边缘仍然存在问题,我不确定如何解决。

import matplotlib.pyplot as plt
import numpy as np
import scipy.ndimage

# data ranges
xr = [5., 8.]
yr = [0., 22.]

# pixel widths
x_pw = np.diff(xr) / (KS_imshow.shape[1])
y_pw = np.diff(yr) / (KS_imshow.shape[0])

# plot the image
plt.imshow(KS_imshow, extent=xr+yr, origin='lower', interpolation='nearest',
        aspect='auto', cmap='Blues', vmin=0., vmax=1.)
cbar = plt.colorbar()

# upscale by a factor of 50 (might be an issue for large arrays)
highres = scipy.ndimage.zoom(KS_imshow, 50, order=0, mode='nearest') 

# correct the extent by the pixel widths
extent = np.array(xr+yr) + np.array([x_pw, -x_pw, y_pw, -y_pw]).flatten()/2

# create the contours
CS2 = plt.contour(highres, levels=[0.5], extent=extent, origin='lower',
        colors='r', linewidths=2)
cbar.add_lines(CS2)

plt.show()

结果:

但是,为了显示 0.5 的阈值,我建议自定义颜色图而不是使用等高线:

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

blues = plt.cm.Blues(np.linspace(0,1,200))
reds = plt.cm.Reds(np.linspace(0,1,200))
colors = np.vstack((blues[0:128,:], reds[-129:,:]))

i = np.linspace(0,1,256)
r = np.column_stack((i, colors[:-1,0], colors[1:,0]))
g = np.column_stack((i, colors[:-1,1], colors[1:,1]))
b = np.column_stack((i, colors[:-1,2], colors[1:,2]))
d = dict(red=r, green=g, blue=b)
mycmap = mcolors.LinearSegmentedColormap('mymap', d, N=256)

plt.imshow(KS_imshow, extent=[5, 8, 0, 22], origin='lower',
        interpolation='nearest', aspect='auto', cmap=mycmap,
        vmin=0., vmax=1.)

cbar = plt.colorbar()

plt.show()

结果:

作为对@hitzig 的精彩回答的补充,我提供了一些代码,可以更轻松地绘制直线等高线。但是,基本原理是完全一样的。

我们只需要

然后我们可以使用 big_data = np.kron(data, np.ones((factor, factor))) 放大数据并使用 big_data 数组绘制等高线。我们通过传递原始数据的范围来确保图像的大小保持不变。

示例:

# Make up some data
data = np.zeros((10, 20))
data[2:4, 2:8] = 1 + np.random.random((2,6))

# Extent of the data into x and y directions
# (left, right, bottom, top)
extent = [0, 20, 0, 10]

# Plot the data a few times. Each time, the contours
# get drawn based on "enlarged" data to some factor
enlargement_factors = [1, 2, 10]
fig, axs = plt.subplots(len(enlargement_factors), 1)

for i, fac in enumerate(enlargement_factors):
    # Draw the data
    im = axs[i].imshow(data, origin='lower', aspect='auto', extent=extent)

    # Scale the data up (enlarge) ... or leave equal if fac==1
    big_data = np.kron(data, np.ones((fac, fac)))

    # Draw the contour lines of the data
    axs[i].contour(big_data, levels=[0.5], extent=extent, colors='w')
    axs[i].set_title('Enlargement factor: {}'.format(fac))

fig.tight_layout()