简体   繁体   English

根据大小和方向为 matplotlib 颤动场着色

[英]Color matplotlib quiver field according to magnitude and direction

I'm attempting to achieve the same behavior as this function in Matlab , whereby the color of each arrow corresponds to both its magnitude and direction, essentially drawing its color from a wheel.我试图在 Matlab 中实现与此函数相同的行为,其中每个箭头的颜色对应于它的大小和方向,基本上是从轮子上绘制它的颜色。 I saw this question , but it only seems to work for barbs .我看到了这个问题,但它似乎只适用于barbs I also saw this answer, but quiver complains that the color array must be two-dimensional.我也看到了这个答案,但是quiver抱怨颜色数组必须是二维的。

What is the best way to compute C for matplotlib.pyplot.quiver , taking into account both magnitude and direction?考虑到幅度和方向,为matplotlib.pyplot.quiver计算C的最佳方法是什么?

Even though this is quite old now, I've come across the same problem.尽管这已经很老了,但我遇到了同样的问题。 Based on matplotlibs quiver demo and my own answer to this post , I created the following example.基于matplotlibs quiver 演示我自己对这篇文章的回答,我创建了以下示例。 The idea is to convert the angle of a vector to the color using HSV colors Hue value.这个想法是使用HSV 颜色色调值将矢量的角度转换为颜色 The absolute value of the vector is used as the saturation and the value.矢量的绝对值用作饱和度和值。

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

def vector_to_rgb(angle, absolute):
    """Get the rgb value for the given `angle` and the `absolute` value

    Parameters
    ----------
    angle : float
        The angle in radians
    absolute : float
        The absolute value of the gradient
    
    Returns
    -------
    array_like
        The rgb value as a tuple with values [0..1]
    """
    global max_abs

    # normalize angle
    angle = angle % (2 * np.pi)
    if angle < 0:
        angle += 2 * np.pi

    return matplotlib.colors.hsv_to_rgb((angle / 2 / np.pi, 
                                         absolute / max_abs, 
                                         absolute / max_abs))

X = np.arange(-10, 10, 1)
Y = np.arange(-10, 10, 1)
U, V = np.meshgrid(X, Y)

angles = np.arctan2(V, U)
lengths = np.sqrt(np.square(U) + np.square(V))

max_abs = np.max(lengths)
c = np.array(list(map(vector_to_rgb, angles.flatten(), lengths.flatten())))

fig, ax = plt.subplots()
q = ax.quiver(X, Y, U, V, color=c)

plt.show()

结果图

The color wheel is the following.色轮如下。 The code for generating it is mentioned in the Edit.编辑中提到了生成它的代码。


Edit编辑

I just noticed, that the linked matlab function "renders a vector field as a grid of unit-length arrows. The arrow direction indicates vector field direction, and the color indicates the magnitude".我刚刚注意到,链接的 matlab 函数“将矢量场呈现为单位长度箭头的网格。箭头方向表示矢量场方向,颜色表示幅度”。 So my above example is not really what is in the question.所以我上面的例子并不是真正的问题。 Here are some modifications.这里有一些修改。

The left graph is the same as above.左图与上图相同。 The right one does, what the cited matlab function does: A unit-length arrow plot with the color indicating the magnitude.正确的是,引用的 matlab 函数的作用是:单位长度的箭头图,颜色表示幅度。 The center one does not use the magnitude but only the direction in the color which might be useful too.中心不使用大小,而只使用颜色中的方向,这也可能有用。 I hope other combinations are clear from this example.我希望从这个例子中可以清楚地看出其他组合。

结果图

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

def vector_to_rgb(angle, absolute):
    """Get the rgb value for the given `angle` and the `absolute` value

    Parameters
    ----------
    angle : float
        The angle in radians
    absolute : float
        The absolute value of the gradient
    
    Returns
    -------
    array_like
        The rgb value as a tuple with values [0..1]
    """
    global max_abs

    # normalize angle
    angle = angle % (2 * np.pi)
    if angle < 0:
        angle += 2 * np.pi

    return matplotlib.colors.hsv_to_rgb((angle / 2 / np.pi, 
                                         absolute / max_abs, 
                                         absolute / max_abs))

X = np.arange(-10, 10, 1)
Y = np.arange(-10, 10, 1)
U, V = np.meshgrid(X, Y)

angles = np.arctan2(V, U)
lengths = np.sqrt(np.square(U) + np.square(V))
max_abs = np.max(lengths)

# color is direction, hue and value are magnitude
c1 = np.array(list(map(vector_to_rgb, angles.flatten(), lengths.flatten())))

ax = plt.subplot(131)
ax.set_title("Color is lenth,\nhue and value are magnitude")
q = ax.quiver(X, Y, U, V, color=c1)

# color is length only
c2 = np.array(list(map(vector_to_rgb, angles.flatten(), 
                                      np.ones_like(lengths.flatten()) * max_abs)))

ax = plt.subplot(132)
ax.set_title("Color is direction only")
q = ax.quiver(X, Y, U, V, color=c2)

# color is direction only
c3 = np.array(list(map(vector_to_rgb, 2 * np.pi * lengths.flatten() / max_abs, 
                                      max_abs * np.ones_like(lengths.flatten()))))

# create one-length vectors
U_ddash = np.ones_like(U)
V_ddash = np.zeros_like(V)
# now rotate them
U_dash = U_ddash * np.cos(angles) - V_ddash * np.sin(angles)
V_dash = U_ddash * np.sin(angles) + V_ddash * np.cos(angles)

ax = plt.subplot(133)
ax.set_title("Uniform length,\nColor is magnitude only")
q = ax.quiver(X, Y, U_dash, V_dash, color=c3)

plt.show()

To plot the color wheel use the following code.要绘制色轮,请使用以下代码。 Note that this uses the max_abs value from above which is the maximum value that the color hue and value can reach.请注意,这使用了上面的max_abs值,这是色调和值可以达到的最大值。 The vector_to_rgb() function is also re-used here. vector_to_rgb()函数也在这里重用。

ax = plt.subplot(236, projection='polar')

n = 200
t = np.linspace(0, 2 * np.pi, n)
r = np.linspace(0, max_abs, n)
rg, tg = np.meshgrid(r, t)

c = np.array(list(map(vector_to_rgb, tg.T.flatten(), rg.T.flatten())))
cv = c.reshape((n, n, 3))

m = ax.pcolormesh(t, r, cv[:,:,1], color=c, shading='auto')
m.set_array(None)
ax.set_yticklabels([])

I don't know if you've since found that quiver with matplotlib 1.4.x has 3d capability.我不知道您是否发现带有 matplotlib 1.4.x 的 quiver 具有 3d 功能。 This capability is limited when attempting to colour the arrows however.但是,在尝试为箭头着色时,此功能受到限制。

A friend and I write the following script (in half an hour or so) to plot my experiment data using hex values from a spreadsheet, for my thesis.我和一个朋友为我的论文编写了以下脚本(半小时左右),使用电子表格中的十六进制值绘制我的实验数据。 We're going to make this more automated once we're done with the semester but the issue with passing a colour map to quiver is that it can't accept a vector form for some reason.一旦我们完成这个学期,我们将使其更加自动化,但是将颜色映射传递给 quiver 的问题是由于某种原因它不能接受矢量形式。

This link is to my git repository where the code I used, slightly neatened up by another friend, is hosted. 此链接指向我的 git 存储库,其中托管了我使用的、由另一位朋友稍微整理的代码。

I hope I can save someone the time it took me.我希望我能在我花费的时间里救人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM