在“uv”模式下绘图时获取箭袋箭头(尖端和底部)的坐标

lho*_*ert 7 python matplotlib

我想做什么

我希望在“uv”模式下绘图时能够获得箭袋箭头的坐标,以便重新使用这些数据来绘制其他形状(例如椭圆)。

问题

这个问题也和这个帖子有关。在这篇文章中,答案提到使用._pathsquiver 变量来获取箭头的坐标。但是,没有迹象表明如何做到这一点。

有人有解决方案可以在“uv”绘图模式下访问与箭头顶部和底部关联的坐标吗?有很多变量q._paths,我看不出哪个是相关的。

复制代码

下面的代码在“xy”模式下工作得很好:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib.patches import Ellipse
import matplotlib.transforms as transforms

#-------------------------------------
# Variable definition
colsec = 'royalblue'
colvec = 'salmon'
colellipse = 'limegreen'
x = np.array([ 0.00789308, -0.0773587 ,  0.03353797, -0.06185714, -0.13095092,
        0.03280368,  0.04775701, -0.08124051, -0.02894444, -0.02834356,
       -0.1457362 , -0.00628834,  0.09627607])
y = np.array([-0.03668553,  0.05931522, -0.04041772, -0.00866234, -0.00539877,
       -0.14787117, -0.21553271, -0.15741139, -0.1417963 , -0.00887117,
        0.02207362, -0.11979755, -0.28635583])
meanx = np.mean(x)
meany = np.mean(y)

# ellipse parameter
ell_radius_x = 0.54
ell_radius_y = 1.30
scale_x = 0.07
scale_y = 0.1

#-------------------------------------
# 'xy' plot

posx1 = 0
posy1 = 0
    
# Plot
fig, ax = plt.subplots(figsize=(8, 8))
plt.scatter(x,y,color='blue')

# Quiver plot
Qv = ax.quiver(posx1, posy1, meanx,  meany,
              angles='xy', scale_units='xy', scale=1,
              color='black')

# Basic ellipse definition
ellipse = Ellipse((0, 0),
        width=ell_radius_x * 2,
        height=ell_radius_y * 2,
        facecolor='none',
        edgecolor='red')

center=(meanx + posx1, meany + posy1)

# Transformation of the ellipse according to external parameters (obtained from various statistics on the data)
transf = transforms.Affine2D() \
        .rotate_deg(45) \
        .scale(scale_x, scale_y) \
        .translate(*center)
ellipse.set_transform(transf + ax.transData)
    
# Plot of the ellipse
ax.plot(*center,'x',color='g',markersize=12)    
    
ax.add_patch(ellipse)

Run Code Online (Sandbox Code Playgroud)

我们得到了预期的结果: 椭圆和箭袋 'xy' 模式

现在,当我切换到 'uv' 模式时(我的箭袋位置有不同的单位),虽然我尝试使用缩放因子,但我无法重现相同的图。下面的代码给了我这个结果: 在此处输入图片说明

#-------------------------------------
# 'uv' plot (variables are defined previously)

# Scale factor for quiver and ellipse plot
scalefac = 2

posx1 = np.array(-12.633)
posy1 = np.array(57.533)

# Plot
fig, ax = plt.subplots(figsize=(8, 8))
plt.scatter(posx1,posy1,color='blue')

Qv = ax.quiver(posx1, posy1, meanx*scalefac,  meany*scalefac,
              scale=1, scale_units='width',
              color='black')

# Basic ellipse definition
ellipse = Ellipse((0, 0),
        width=ell_radius_x * 2,
        height=ell_radius_y * 2,
        facecolor='none',
        edgecolor='red')

# Transformation of the ellipse according to external parameters (obtained from various statistics on the data)
center=(meanx*scalefac + posx1, meany*scalefac + posy1)
transf = transforms.Affine2D() \
        .rotate_deg(45) \
        .scale(scale_x*scalefac, scale_y*scalefac) \
        .translate(*center)
ellipse.set_transform(transf + ax.transData)
    
# Plot of the ellipse
ax.plot(*center,'x',color='g',markersize=12)    
    
ax.add_patch(ellipse)

Run Code Online (Sandbox Code Playgroud)

Qv._paths 不返回一个易于理解的变量:

print(Qv._paths)
[Path(array([[ 0.00357682, -0.00112643],
       [-0.03897025, -0.13622912],
       [-0.03069018, -0.13490515],
       [-0.05268492, -0.1672941 ],
       [-0.05215112, -0.12814659],
       [-0.0461239 , -0.13397627],
       [-0.00357682,  0.00112643],
       [ 0.00357682, -0.00112643]]), None)]
Run Code Online (Sandbox Code Playgroud)

我想我需要的缩放信息在某个地方,Qv._paths但我不清楚在哪里。这个想法是有一个健壮的方法,这样我就可以改变与我的变量相关的缩放scalefac。有什么建议?

Mer*_*ury 1

又看了一遍医生,我突然明白了。让我绘制一个虚拟示例,以便于理解。

fig, ax = plt.subplots(figsize=(8, 8))
plt.xlim(-12.8,-12.6)
plt.ylim(57.2,57.6)

x1, y1 = -12.633, 57.533
x2, y2 = -12.7, 57.4
angle = np.arctan((y2-y1)/(x2-x1))
D = np.sqrt((x2-x1)**2 + (y2-y1)**2)
U, V = D*np.cos(angle), D*np.sin(angle)
ax.scatter(x2, y2, marker='x', s=100, color='k')
Qv1 = ax.quiver(x1, y1, -U, -V, angles='uv', scale=1, scale_units='xy', color='black')
Qv2 = ax.quiver(x1, y1, -U, -V, angles='xy', scale=1, scale_units='xy', color='red')
Run Code Online (Sandbox Code Playgroud)

考虑(x2, y2)类似于假设椭圆的中心。我们可以用简单的向量数学来计算角度和 U、V 分量。将上式绘制得到:

Qv1 和 Qv2

请注意紫外线角度中的颤动是如何稍微偏离的,与问题中的示例相同。但是,如果您阅读 matplotlib 文档中的文档,它会说:

'uv':箭头轴纵横比为 1,因此如果 U == V,则绘图上箭头的方向与水平轴逆时针方向成 45 度(向右为正)。

在 uv 模式下,箭头的轴独立于 x,y 轴,并且该轴的纵横比为 1。因此,自然地,如果您的绘图的纵横比为 1,则箭头应该完美匹配!

plt.xlim(-12.8,-12.4)
plt.ylim(57.2,57.6)
Run Code Online (Sandbox Code Playgroud)

在这个 xlim 和 ylim 设置下,如果我运行之前的虚拟图,我们会得到:

匹配Qv

回到您的示例,您需要将scale_units更改为“xy”,并简单地设置纵横比为1的xlim、ylim。

#-------------------------------------
# 'uv' plot (variables are defined previously)

# Scale factor for quiver and ellipse plot
scalefac = 2

posx1 = np.array(-12.633)
posy1 = np.array(57.533)

# Plot
fig, ax = plt.subplots(figsize=(8, 8))
plt.scatter(posx1,posy1,color='blue')

Qv = ax.quiver(posx1, posy1, meanx*scalefac,  meany*scalefac,
              angles='uv', scale=1, scale_units='xy',
              color='black')

# Basic ellipse definition
ellipse = Ellipse((0, 0),
        width=ell_radius_x * 2,
        height=ell_radius_y * 2,
        facecolor='none',
        edgecolor='red')

# Transformation of the ellipse according to external parameters (obtained from various statistics on the data)
center=(meanx*scalefac + posx1, meany*scalefac + posy1)
transf = transforms.Affine2D() \
        .rotate_deg(45) \
        .scale(scale_x*scalefac, scale_y*scalefac) \
        .translate(*center)
ellipse.set_transform(transf + ax.transData)
    
# Plot of the ellipse
ax.plot(*center,'x',color='g',markersize=12)    
    
ax.add_patch(ellipse)
plt.xlim(-13,-12.5)
plt.ylim(57.1, 57.6)
Run Code Online (Sandbox Code Playgroud)

正确的 Qv

也许应该在 matplotlib 文档中添加额外的警告或注释,因为我认为乍一看这并不明显。