根据大小和方向为 matplotlib 颤动场着色 [英] Color matplotlib quiver field according to magnitude and direction

查看:109
本文介绍了根据大小和方向为 matplotlib 颤动场着色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现与

以下是色轮.编辑中提到了生成它的代码.


编辑

我刚刚注意到,链接的 matlab 函数将向量场呈现为单位长度箭头的网格.箭头方向指示矢量场方向,而颜色指示大小.因此,我上面的示例并不是问题所在.这里有一些修改.

左图与上图相同.右边的函数就是所引用的matlab函数的函数:单位长度的箭头图,其中的颜色表示幅度.中间的一个不使用幅度,而仅使用颜色中可能有用的方向.我希望从这个例子中可以清楚地看出其他组合.

 将numpy导入为np导入 matplotlib.colors导入matplotlib.pyplot作为pltdef vector_to_rgb(角度,绝对):"""获取给定`angle`和`absolute`值的rgb值参数----------角度:浮动弧度角绝对:浮点数梯度的绝对值退货-------类似数组rgb值作为具有值[0..1]的元组"全局 max_abs# 标准化角度角度 = 角度 % (2 * np.pi)如果角度<0:角度 += 2 * np.pi返回matplotlib.colors.hsv_to_rgb((angle/2/np.pi,绝对/max_abs,绝对/max_abs))X = np.arange(-10, 10, 1)Y = np.arange(-10, 10, 1)U,V = np.meshgrid(X,Y)角度 = np.arctan2(V, U)长度 = np.sqrt(np.square(U) + np.square(V))max_abs = np.max(长度)# 颜色是方向,色调和值是大小c1 = np.array(list(map(vector_to_rgb,angles.flatten(),lengths.flatten())))ax = plt.subplot(131)ax.set_title(颜色是长度,\ nhue,值是大小")q = ax.quiver(X, Y, U, V, color=c1)# 颜色只是长度c2 = np.array(list(map(vector_to_rgb,angles.flatten(),np.ones_like(lengths.flatten())* max_abs)))斧= plt.subplot(132)ax.set_title(颜色仅代表方向")q = ax.quiver(X,Y,U,V,color = c2)#颜色仅是方向c3 = np.array(list(map(vector(vector_to_rgb,2 * np.pi * lengths.flatten()/max_abs,max_abs * np.ones_like(lengths.flatten())))#创建一个长度向量U_ddash = np.ones_like(U)V_ddash = np.zeros_like(V)#现在旋转它们U_dash = U_ddash * np.cos(angles) - V_ddash * np.sin(angles)V_dash = U_ddash * np.sin(角度)+ V_ddash * np.cos(角度)ax = plt.subplot(133)ax.set_title(长度一致,\n颜色仅代表大小")q = ax.quiver(X,Y,U_dash,V_dash,color = c3)plt.show()


要绘制色轮,请使用以下代码.请注意,这从上方开始使用 max_abs 值,该值是色相和值可以达到的最大值.vector_to_rgb() 函数也在这里重用.

  ax = plt.subplot(236,projection ='polar')n = 200t = 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(无)ax.set_yticklabels([])

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. I saw this question, but it only seems to work for barbs. I also saw this answer, but quiver complains that the color array must be two-dimensional.

What is the best way to compute C for matplotlib.pyplot.quiver, taking into account both magnitude and direction?

解决方案

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. The idea is to convert the angle of a vector to the color using HSV colors Hue value. 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". 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. 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. The vector_to_rgb() function is also re-used here.

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([])

这篇关于根据大小和方向为 matplotlib 颤动场着色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆