在等高线上绘制点 - Matplotlib / Python

8 投票
2 回答
17859 浏览
提问于 2025-04-18 13:01

我正在尝试用Matplotlib绘制一些点在等高线图上。

我有一个标量场,想要在这个场上绘制等高线。不过,我的ndarray的维度是0 x 20,而我的实际空间范围是从-4到4。

我可以用这段代码绘制等高线:

x, y = numpy.mgrid[-4:4:20*1j, -4:4:20*1j]

# Draw the scalar field level curves
cs = plt.contour(scalar_field, extent=[-4, 4, -4, 4])
plt.clabel(cs, inline=1, fontsize=10)

问题是我需要在这个图上绘制一些点,而这些点是通过ndarray得到的,也就是说,我得到的点是根据这个数组的维度变化的。

我尝试用这段代码来绘制这些点:

def plot_singularities(x_dim, y_dim, steps, scalar_field, min_points, max_points, file_path):
    """
    :param x_dim : the x dimension of the scalar field
    :param y_dim : the y dimension of the scalar field
    :param steps : the discretization of the scalar field
    :param file_path : the path to save the data
    :param scalar_field : the scalar_field to be plot
    :param min_points : a set (x, y) of min points of the scalar field
    :param max_points : a set (x, y) of max points of the scalar field
    """
    min_points_x = min_points[0]
    min_points_y = min_points[1]
    max_points_x = max_points[0]
    max_points_y = max_points[1]

    plt.figure()

    x, y = numpy.mgrid[-x_dim:x_dim:steps*1j, -y_dim:y_dim:steps*1j]

    # Draw the scalar field level curves
    cs = plt.contour(scalar_field, extent=[-x_dim, x_dim, -y_dim, y_dim])
    plt.clabel(cs, inline=1, fontsize=10)

    # Draw the min points
    plt.plot(min_points_x, min_points_y, 'ro')

    # Draw the max points
    plt.plot(max_points_x, max_points_y, 'bo')

    plt.savefig(file_path + '.png', dpi=100)
    plt.close()

但是我得到的图像是这样的:

enter image description here

这并不正确。

如果我把这一行:

cs = plt.contour(scalar_field, extent=[-x_dim, x_dim, -y_dim, y_dim])

换成这一行:

cs = plt.contour(scalar_field)

enter image description here

我得到了想要的效果,但这个范围并没有显示我的实际数据空间,而是显示了ndarray的维度。

最后,如果我不绘制这些点(注释掉plot()的行),我可以得到我想要的范围:

enter image description here

但我必须绘制这些点。两个数据是在同一个空间里的。
不过contour()函数让我可以指定网格。我想找到一种方法在绘制点的时候做到这一点。

我该如何正确设置范围呢?

2 个回答

0

你想在真实的数据空间里同时画出轮廓线和点,对吧?plt.contour 这个函数会使用你手里的二维数组对应的 x 和 y 值,然后在坐标轴上正确地绘制出来。

xvals = -x_dim:x_dim:step  # I'm not sure about these ... but you get the idea
yvals = -y_dim:y_dim_step
plt.contour(xvals, yvals, scalar_field)
5

如果你没有提供与标量场对应的 xy 数据,contour 就会使用从 0 开始的整数值,直到数组的大小。这就是为什么坐标轴显示的是数组的维度。参数 extent 应该给出最小和最大的 xy 值;我猜这就是你所说的“数据空间”。所以调用 contour 的方式应该是:

contour(scalar_field,extent=[-4,4,-4,4])

你可以通过指定 xy 数据来重现这个效果:

contour(numpy.linspace(-4,4,20),numpy.linspace(-4,4,20),scalar_field)

这样的话,轮廓图就会和你第一个图完全一样。我猜之所以不正确,是因为最小和最大点的位置不对。根据你提供的信息,这是因为你传给函数的 min_pointsmax_points 是数组 scalar_field索引,所以它们对应的是整数,而不是实际的 xy 值。试着用这些索引来访问 xy 点,可以这样定义:

x=numpy.linspace(-4,4,20)
y=numpy.linspace(-4,4,20)

举个例子,如果你的最小点是 (0,1),那么它对应的就是 (x[0], y[1])。我觉得用 mgrid 也可以做到类似的事情,不过我自己从来没有用过。

撰写回答