numpy数组梯度的反向顺序和matplotlib箭头图

4

我正在使用numpy 1.6和matplotlib 1.1.1,尝试从我拥有的标量场生成速度场。到目前为止,我是这样生成我的标量数据的:

    num_samples = 50
    dim_x = np.linspace(self.min_x, self.max_x,num_samples)
    dim_y = np.linspace(self.min_y, self.max_y,num_samples)
    X, Y = np.meshgrid(dim_x, dim_y)

    len_x = len(dim_x)
    len_y = len(dim_y)

    a = np.zeros([len_x, len_y], dtype=float)
    for i, y in enumerate(dim_y):
        for j, x in enumerate(dim_x):
            a[i][j] = x*y # not exactly my function, just an example

然后我得到了渐变色:
   (velx,vely) =  np.gradient(a)

从numpy文档中可以看到,velx是向量场的x分量,而vely是y分量。查看matplotlib文档,使用quiver函数绘制矢量场时,它说明velx和vely分别是向量场的x和y分量:

    fig0 = plt.figure()
    ax = fig0.add_subplot(111)
    Q = ax.quiver(X,Y, velx, vely )
    plt.show()

这会给出速度场的错误结果:

标量场的错误结果

唯一让图形看起来正常的方法是反转quiver上的组件:

    Q = ax.quiver(X,Y, vely, velx )#WHY???

带“错误”表达式的正确结果

我怀疑这类似行列排序,但是如果np.gradient的输出被倒置了,或者quiver被倒置了,我就搞不清楚了。所有一维问题都按预期工作。谢谢!

编辑:为了更加清晰地说明这种情况如何倒置,请更改函数。

a[i][j] = x*y

to

a[i][j] = x*x

渐变应该在x方向上,随着x的增加而增加。结果仍然不正确:如果我使用

Q = ax.quiver(X,Y, velx, vely )

我理解为

仍然错误

如果我将其反转

Q = ax.quiver(X,Y, vely, velx )

我明白了

正确

或许有一种更符合Python风格(且正确的)方法可以实现...

1个回答

3
我认为你是对的,(这是一个数组排序问题)。a 是按照 a[yidx,xidx] 构建的,但当你取梯度时,你做了:velx, vely = np.gradient(a),而你应该这样做:vely, velx = np.gradient(a)。由于沿着0轴的梯度应该给出 vely(可能是 d/dy(a) = vely)?——除非我漏掉了什么(在这种情况下,我会很高兴删除这个答案)。
另外请注意,我认为你可以不用嵌套列表来构建 "a":
a = X*Y

这应该也适用于更复杂的函数...


谢谢您的回答!您能否解释一下我如何构建a[yidx,xidx]数组?我认为第二个for循环中的索引j是用于行即x值,反之亦然?如果您是正确的,那么在循环中应该倒转顺序,但是这会造成轮廓和contourf方面的问题... - Ivan
@Ivan -- 简单来说,在你的循环中,当迭代dim_y时返回i,在迭代dim_x时返回j。然后将元素打包为a[i,j]。我有遗漏什么吗(完全有可能)。 - mgilson
你说得完全正确。我对元素的顺序搞混了,非常困惑应该是 x == i 还是 y == j。 - Ivan
1
@ivan -- 一般来说,我已经不再考虑“行”和“列”。这些术语适用于矩阵。你有一个二维数组,而不是矩阵。对我来说,最容易将给定的维度与特定轴关联起来。这意味着当我在该轴上迭代时,我会得到其中轴值恒定的切片。我不确定这种描述是否有帮助...(如果没有,请忽略此评论)。 - mgilson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接