通过读取数据使用 matplotlib 制作 3D 箭袋图

making a 3D quiver plot using matplotlib by reading in data

我正在尝试使用 matplotlib 2.2.5 制作 3D 箭袋图。我在下面提供了一个简单的示例代码来展示我的尝试。我想使用 fx(x,y,z)、fy(x,y,z) 和 fz(x,y,z) 绘制箭袋图。这些对应于矢量场 f = (fx,fy,fz)。我将 fx、fy、fz 的数据输入为 3 个 .dat 文件,其中每个 .dat 文件是 1 列数字。

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt #I'm using matplotlib 2.2.5
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

fx = np.genfromtxt('fx.dat')
fy = np.genfromtxt('fy.dat')
fz = np.genfromtxt('fz.dat')

N = 10
Fx = fx[::N,::N]
Fy = fy[::N,::N]
Fz = fz[::N,::N]

nrows, ncols = Fx.shape
nx = 1
ny = 1
nz = 1

x = np.linspace(-nx, nx, ncols)
y = np.linspace(-ny, ny, ncols)
z = np.linspace(-nz, nz, ncols)
xi, yi, zi = np.meshgrid(x, y, z, indexing='ij')

plt.quiver(xi, yi, zi, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5)

plt.axis('scaled')
plt.show()

数据生成和存储如下(使用fortran):

!generate data
DO i = -nx,nx !nx = 1
  DO j = -ny,ny !ny = 1
     DO k = -nz,nz !nz = 1
       fx(i,j,k) = i + 2.*j  + 3.*k  !this is a function fx that depends on x,y,z; fx(x,y,z)
       fy(i,j,k) = i - 4.*j  + k !this is a function fy that depends on x,y,z; fy(x,y,z)
       fz(i,j,k) = i + 2*j + k !this is a function fz that depends on x,y,z; fz(x,y,z)
     END DO
  END DO
END DO

!store data
DO i = -nx,nx
   DO j = -ny,ny
      DO k = -nz,nz
        WRITE(1,*) fx(i,j,k) !stores fx(x,y,z)
        WRITE(2,*) fy(i,j,k) !stores fy(x,y,z)
        WRITE(3,*) fz(i,j,k) !stores fz(x,y,z)
      END DO
   END DO
END DO

我在这里假设您正在尝试从(原点 (0,0,0))开始绘制箭袋。

使用坐标在 -1 和 1 之间的随机样本(希望它与您的数据样本匹配),这将是这样的:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')

fx = np.genfromtxt('fx.dat')
fy = np.genfromtxt('fy.dat')
fz = np.genfromtxt('fz.dat')

N = 10
Fx = fx[:N]
Fy = fy[:N]
Fz = fz[:N]

请注意,我使用了一个简单的“:”:根据您的解释,您的 .dat 文件只有一个维度。仅当至少有 2 个维度时才使用倍数冒号。

plt.quiver(0, 0, 0, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5) #To plot starting from the origin

ax.set_xlim(-1,1)
ax.set_ylim(-1,1)
ax.set_zlim(-1,1)

plt.show()

如果你想从你的网格开始绘制(即np.linspace),你可以改变代码如下(虽然我不确定这是你想要实现的):

nx = 1
ny = 1
nz = 1
x = np.linspace(-nx, nx, N)
y = np.linspace(-ny, ny, N)
z = np.linspace(-nz, nz, N)
plt.quiver(x, y, z, Fx, Fy, Fz, edgecolor='k', facecolor='black', linewidth=.5)
ax.set_xlim(-2,2) #I altered the bounds to match the new coordinates 
ax.set_ylim(-2,2)
ax.set_zlim(-2,2)

注意:此代码仅在 matplotlib 3.0.1 上进行了测试