gpt4 book ai didi

python - 在 Python 中绘制 3D 矢量场

转载 作者:行者123 更新时间:2023-12-04 13:07:37 28 4
gpt4 key购买 nike

数据
我有一个向量场,除了 z 分量外,所有分量都为 0。我只有这个字段的一部分的数据。我的目标是在 3D 图中显示这个切片。
切片:
enter image description here

import numpy as np
import matplotlib.pyplot as plt

# DATA FIELD (1,N,M)
dz = np.array([[[0.24884899, 0.24884899, 0.24884899, 0.24884899, 0.24884899,
0.24884899],
[0.248849 , 0.248849 , 0.248849 , 0.248849 , 0.248849 ,
0.248849 ],
[0.24885767, 0.24885513, 0.24885108, 0.24885113, 0.2488552 ,
0.24885767],
[0.2451304 , 0.24563262, 0.24642831, 0.24641793, 0.24561579,
0.2451304 ],
[0.0764377 , 0.12581053, 0.09866768, 0.10043774, 0.12461962,
0.0764377 ],
[0.03382106, 0.03394624, 0.03414449, 0.03414171, 0.03394174,
0.03382106]]])

dx = np.zeros(np.shape(dz))
dy = np.zeros(np.shape(dz))

# DATA POINTS (N,)
X = np.array([0. , 0.2, 0.4, 0.6, 0.8, 1. ])
Y = X
Z = np.array([-500., -360., -220., -80., 60., 200.])
要创建绘图:
# COMPUTE LENGTH OF VECTORS
length = np.sqrt(dx[0]**2+ dz[0]**2)

# PLOT 2D Cross-Section of vector field
fig = plt.figure(dpi=300)
Q = plt.quiver(X, Z, dx[0], dz[0], length, units='xy' ,angles='xy', scale=0.005,
pivot = "tail", headaxislength = 5, headlength = 5, cmap='jet')
fig.colorbar(Q)
plt.gca().invert_yaxis()
plt.ylabel("Z")
plt.xlabel("X")
plt.title("2D Cross-Section")
问题
到目前为止一切顺利,但是 当我尝试在 3D 中绘制它时,似乎我做错了 ,因为
  • 箭头不再可见
  • 情节似乎旋转了
  • # Create 3D Quiver Plot with color gradient
    # Source: https://stackoverflow.com/questions/65254887/how-to-plot-with-matplotlib-a-3d-quiver-plot-with-color-gradient-for-length-giv

    from mpl_toolkits.mplot3d import Axes3D # <--- This is important for 3d plotting

    def plot_3d_quiver(x, y, z, u, v, w):
    # COMPUTE LENGTH OF VECTOR -> MAGNITUDE
    c = np.sqrt(np.abs(v)**2 + np.abs(u)**2 + np.abs(w)**2)

    c = (c.ravel() - c.min())/c.ptp()
    # Repeat for each body line and two head lines
    c = np.concatenate((c, np.repeat(c, 2)))
    # Colormap
    c = plt.cm.jet(c)

    fig = plt.figure(dpi = 300)
    ax = fig.gca(projection = '3d')
    ax.quiver(x, y, z, u, v, w, colors = c, length = 1, arrow_length_ratio = 0.5)
    plt.gca().invert_zaxis()
    plt.show()


    # Create Mesh !
    xi, yi, zi = np.meshgrid(X, Y, Z, indexing = 'xy')

    # slice mesh
    skip_every = 1
    skip_slice = 6
    skip3D = (slice(None, None, skip_slice), slice(None, None, skip_every), slice(None, None, skip_every))

    plot_3d_quiver(xi[skip3D], yi[skip3D], zi[skip3D], dx, dy, dz)
    enter image description here
    接下来我可以尝试什么来解决这个问题?
    编辑
    正如@Marc 所指出的,箭头在 3D 图中,但显然,箭头大小与轴的大小有关。在此处查看更多信息: https://github.com/matplotlib/matplotlib/issues/11746
    到目前为止,除了将所有轴缩放到大致相同的值之外,似乎没有其他解决方法。所以,如果 - 按照@Marc 的建议 - 我将 z 轴除以 1000,我可以再次看到箭头:
    plot_3d_quiver(xi[skip3D], yi[skip3D], zi[skip3D]/1000, dx, dy, dz)
    然后我们得到:
    enter image description here
    这清楚地表明方向在某种程度上偏离了。
    编辑 2
    我想达到的目标:
    我拥有的数据仅用于 3D 空间的一个横截面(一个平面)(-> 维度 (1,N,M)),因此如果我以 3D 形式显示它,它应该如下所示:
    enter image description here
    完整数据
    最后,我想正确绘制完整的矢量场。
    你可以在这里下载: https://filebin.net/csjvs7xde5lfbwek
    # %% 
    import pickle
    import numpy as np
    import matplotlib.pyplot as plt

    # Import Full Data
    with open('full_data.pickle', 'rb') as handle:
    full_data = pickle.load(handle)

    # Axis
    X = np.linspace(0,1,101)
    Y = np.linspace(0,1,10)
    Z = np.linspace(-500,200,101)

    for cross_section in full_data["cross_sections"].keys():

    # extract field components in x, y, and z
    dx,dy,dz = full_data["cross_sections"][cross_section]

    # Make them numpy imediatley
    dx = np.array(dx)
    dy = np.array(dy)
    dz = np.array(dz)



    # ------------------------
    # plot cross-sections z-x
    # -----------------------

    length=np.sqrt(dx**2+dz**2)

    fig = plt.figure(dpi=300)

    skip_every = 10
    skip_slice = 2
    skip1D= slice(None,None,skip_every)
    skip2D=(slice(None,None,skip_every),slice(None,None,skip_every))

    # If U and V are 2-D arrays and X and Y are 1-D,
    # and if len(X) and len(Y) match the column and row dimensions of U,
    # then X and Y will be expanded with numpy.meshgrid().
    # To make the head a triangle, make headaxislength the same as headlength.
    Q = plt.quiver(X[skip1D], Z[skip1D], dx[skip2D], dz[skip2D],\
    length[skip2D], units='xy' ,angles='xy', scale=0.02,
    pivot = "tail", headaxislength = 5, headlength = 5, cmap='jet')
    fig.colorbar(Q)
    plt.title("Cross-Section: " + str(cross_section))
    # Invert y axis to have same represntation than MC GRATING
    plt.gca().invert_yaxis()

    plt.pause(0.01)

    # ------------------------
    # plot full 3D Vector Field ??
    # -----------------------

    最佳答案

    正如评论中所讨论的:
    箭头
    箭头未显示,因为与 x/y 轴值相比,您的 z 轴数据要大得多。您必须重新调整或提供参数 quiver .
    数据创建
    关于如何创建数据没有通用的好的解决方案。这在很大程度上取决于您的用例。在我看来,一种易于理解和调整的方法如下:

    import numpy as np, matplotlib.pyplot as plt, pandas as pd
    from mpl_toolkits.mplot3d import Axes3D

    def plot_3d_quiver(x, y, z, u, v, w):
    # COMPUTE LENGTH OF VECTOR -> MAGNITUDE
    c = np.sqrt(np.abs(v)**2 + np.abs(u)**2 + np.abs(w)**2)

    c = (c.ravel() - c.min())/c.ptp()
    # Repeat for each body line and two head lines
    c = np.concatenate((c, np.repeat(c, 2)))
    # Colormap
    c = plt.cm.jet(c)

    fig = plt.figure(dpi = 300)
    ax = fig.gca(projection = '3d')
    ax.quiver(x, y, z, u, v, w, colors = c, length = .5, arrow_length_ratio = 0.2)
    plt.gca().invert_zaxis()
    plt.show()

    axis = np.r_[-1:1:.2]
    X,Y,Z = np.meshgrid(axis,axis,axis)

    zeros = np.zeros_like(X)
    U,V,W = (zeros, zeros, zeros+np.linspace(0,-1,len(axis))[:,np.newaxis,np.newaxis])

    plot_3d_quiver(X,Y,Z,U,V,W)

    enter image description here
    编辑
    问题在于您希望如何根据数据对 3D 网格点进行排序。您可以匹配您的数据 dz通过将第三个轴与第二个轴切换到网格网格:
    plot_3d_quiver(xi[skip3D], yi[skip3D], zi[skip3D], dx, dy, np.moveaxis(dz,2,1))
    或者,如果您只使用二维,则可以转置矩阵:
    plot_3d_quiver(xi[0], yi[0], zi[0], dx[0], dy[0], dz[0].T)

    关于python - 在 Python 中绘制 3D 矢量场,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68690442/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com