Brendan Darrer
Brendan Darrer

Reputation: 509

3d quiver plot from .npy data files to give a 3d vector field

I want to plot a 3d velocity vector field using a 3d quiver plot in python, from 3 data files (.npy) that give u, v and w components of velocity in the x, y and z directions. This what I have done so far, showing the error message as well. How do I create a 3d quiver plot from three 3d .npy data files? I have also looked at other examples here and here. The code below was adapted from the 2d quiver plot example from here.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
from mpl_toolkits.mplot3d import proj3d

c1 = 1
nx, ny, nz = 284, 160, 160

x1 = range(nx)
y1 = range(ny)
z1 = range(nz)

U = np.load("u.npy") # 3d array file
V = np.load("v.npy") # 3d array file
W = np.load("w.npy") # 3d array file

X1, Y1, Z1 = np.meshgrid(x1, y1, z1)

fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')
ax.set_title("pivot='mid'; every 10th arrow; units='velocity vector' time=" + str(c1))
Q = ax.quiver(X1[::10, ::10], Y1[::10, ::10], Z1[::10, ::10], U[::10, ::10],
    V[::10, ::10], W[::10, ::10], pivot='mid', units='inches')

#Not sure if it should be formatted as below:
#Q = ax.quiver(X1[::10, ::10, ::10], Y1[::10, ::10, ::10], Z1[::10, ::10, ::10], U[::10, ::10, ::10],
            #V[::10, ::10, ::10], W[::10, ::10, ::10], pivot='mid', units='inches')
qk = ax.quiverkey(Q, 0.9, 0.9, 5, r'$1 \frac{m}{s}$', labelpos='E', coordinates='figure') #possibly for 2D (X, Y) only.
ax.scatter(X1[::10, ::10], Y1[::10, ::10], Z1[::10, ::10], color='c', s=0)
plt.tight_layout()
plt.savefig('3D_video_velocity_' + str(c1) + '.png')

Error message:

$ python3 test_3d_quiver_plot_1a.py 
Traceback (most recent call last):
  File "test_3d_quiver_plot_1a.py", line 69, in <module>
    Q = ax.quiver(X1[::10, ::10], Y1[::10, ::10], Z1[::10, ::10], U[::10, ::10],
  File "/home/brendan/.local/lib/python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 2628, in quiver
    bcast = np.broadcast_arrays(*input_args, *masks)
  File "<__array_function__ internals>", line 5, in broadcast_arrays
  File "/home/brendan/.local/lib/python3.8/site-packages/numpy/lib/stride_tricks.py", line 264, in broadcast_arrays
    shape = _broadcast_shape(*args)
  File "/home/brendan/.local/lib/python3.8/site-packages/numpy/lib/stride_tricks.py", line 191, in _broadcast_shape
    b = np.broadcast(*args[:32])
ValueError: shape mismatch: objects cannot be broadcast to a single shape

The result should look something like this:

enter image description here

Upvotes: 0

Views: 642

Answers (2)

Brendan Darrer
Brendan Darrer

Reputation: 509

I found the following code produced a 3d quiver plot from 3 data files (3d arrrays in .npy files). The code was adapted from @tacaswell.

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np

nx, ny, nz = 160, 284, 160

x1 = range(nx)
y1 = range(ny)
z1 = range(nz)

u = np.load("u.npy")
v = np.load("v.npy")
w = np.load("w.npy")

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

x, y, z = np.meshgrid(x1, y1, z1)

# 3d quiver plot for every 5th data point
ax.quiver(x[::5, ::5], y[::5, ::5], z[::5, ::5], u[::5, ::5], 
    v[::5, ::5], w[::5, ::5], length=0.1, color = 'red', lw=2)

plt.show()

The resultant 3d quiver plot is shown here (I haven't worked out how make the arrows larger yet):enter image description here

Upvotes: 0

Davide_sd
Davide_sd

Reputation: 13150

Based on the above comment, to create a 3D quiver plot X1, Y1, Z1, U, V, W must have the same shape.

Try to modify the following lines of code:

import numpy as np
nx, ny, nz = 160, 284, 160

x1 = range(nx)
y1 = range(ny)
z1 = range(nz)

X1, Y1, Z1 = np.meshgrid(x1, y1, z1)

Note that I changed nx, ny, nz = 284, 160, 160 to nx, ny, nz = 160, 284, 160. This should give X1, Y1, Z1 the correct shape.

Upvotes: 1

Related Questions