我怎样才能在 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()
变量 ri
、phii
和 KS_imshow
在链接文档中。
问题是 imshow
创建了 "pixels",但基础数据只是点(在中心)。因此 contour
对 imshow
创建的图像一无所知。但是,您可以通过放大原始数据然后在其上使用 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 的精彩回答的补充,我提供了一些代码,可以更轻松地绘制直线等高线。但是,基本原理是完全一样的。
我们只需要
- 数据的范围...
- 和
np.kron
然后我们可以使用 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()
我正在用 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()
变量 ri
、phii
和 KS_imshow
在链接文档中。
问题是 imshow
创建了 "pixels",但基础数据只是点(在中心)。因此 contour
对 imshow
创建的图像一无所知。但是,您可以通过放大原始数据然后在其上使用 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 的精彩回答的补充,我提供了一些代码,可以更轻松地绘制直线等高线。但是,基本原理是完全一样的。
我们只需要
- 数据的范围...
- 和
np.kron
然后我们可以使用 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()