I am attempting to create a 3d quiver plot of velocity vectors, using 3 arrays containing the vectors in x, y, z space with respect to time. I.e. a video of the quiver plot. Can someone help with this? I have showed the error message below from running the code as it is.
For example one frame of the output should look a bit like this:
Main code: part 1 and part 2. Also here:
(Note this code was successfully used for the 2D version now being upgraded to 3D)
print("Rendering 'Nucleation and Motion in G gradient in 3D'")
print("Lattice constant dx = {}, time step dt = {}".format(fluid_model_g.dx, fluid_model_g.dt))
for n in progressbar.progressbar(range(args.num_frames)):
fluid_model_g.step()
for _ in range(20):
indices = tf.cast(flow_particles, 'int32')
for index in indices.numpy():
flow_streaks[index[0], index[1]] += 0.15 / args.oversampling
dx = tf.gather_nd(fluid_model_g.u, indices)
dy = tf.gather_nd(fluid_model_g.v, indices)
dz = tf.gather_nd(fluid_model_g.w, indices)
flow_particles = (flow_particles + tf.stack([dx, dy, dz], axis=1) * 400) % x.shape
if n % args.oversampling == 0:
rgb = [
tf.reduce_mean((7*fluid_model_g.G)**2, axis=2) + flow_streaks,
tf.reduce_mean((4*fluid_model_g.Y)**2, axis=2),
tf.reduce_mean((2*fluid_model_g.X)**2, axis=2),
]
frame = make_video_frame(rgb)
writer.append_data(frame)
flow_streaks *= 0
flow_particles = tf.constant(flow_particle_origins, dtype='float64')
#-------------------BJD 22.4.2021----additional rough code at present-----------------------------------------
if n == 200:
print("n = ", n)
break
c1 = c1 + 1
nx, ny, nz = 240, 426, 426
x1 = range(nx)
y1 = range(ny)
z1 = range(nz)
U = np.loadtxt("/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/arrays/quiver3D_array31/u.txt")
V = np.loadtxt("/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/arrays/quiver3D_array31/v.txt")
W = np.loadtxt("/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/arrays/quiver3D_array31/w.txt")
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, ::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')
Q.set_array(np.random.rand(np.prod(x.shape))) # may need this? BJD 22.4.2021
ax.scatter(X1[::10, ::10, ::10], Y1[::10, ::10, ::10], Z1[::10, ::10, ::10], color='c', s=0)
plt.tight_layout()
plt.savefig('/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/plots/3D_video37/3D_video_velocity_' + str(c1) + '.png')
Error message on running code:
brendan@DL380pGen8:~/runs/tf2-model-g_3d_vel_vector/tf2-model-g$ python3 render_video.py /home/brendan/runs/tf2-model-g_2/tf2-model-g/nucleation_3D___3d_velocity_vector__1_seed__y0_x0_____R12_res160pVD20_OS1_ST20___TEST_8th_160.mp4 --params params/nucleation_3D.yaml
2021-04-22 16:44:29.517603: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2021-04-22 16:44:29.517657: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
2021-04-22 16:44:43.078155: I tensorflow/compiler/jit/xla_cpu_device.cc:41] Not creating XLA devices, tf_xla_enable_xla_devices not set
2021-04-22 16:44:43.079068: W tensorflow/stream_executor/platform/default/dso_loader.cc:60] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2021-04-22 16:44:43.079095: W tensorflow/stream_executor/cuda/cuda_driver.cc:326] failed call to cuInit: UNKNOWN ERROR (303)
2021-04-22 16:44:43.079164: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (DL380pGen8): /proc/driver/nvidia/version does not exist
2021-04-22 16:44:43.081520: I tensorflow/compiler/jit/xla_gpu_device.cc:99] Not creating XLA devices, tf_xla_enable_xla_devices not set
Rendering 'Nucleation and Motion in G gradient in 3D'
Lattice constant dx = 0.15, time step dt = 0.041666666666666664
N/A% (0 of 480) | | Elapsed Time: 0:00:00 ETA: --:--:--2021-04-22 16:44:46.312362: I tensorflow/compiler/mlir/mlir_graph_optimization_pass.cc:126] None of the MLIR optimization passes are enabled (registered 2)
2021-04-22 16:44:46.335468: I tensorflow/core/platform/profile_utils/cpu_utils.cc:112] CPU Frequency: 1994870000 Hz
Traceback (most recent call last):
File "render_video.py", line 855, in <module>
episodes[args.episode](writer, args)
File "render_video.py", line 647, in nucleation_3D
fluid_model_g.step()
File "/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/fluid_model_g.py", line 284, in step
np.savetxt("/home/brendan/runs/tf2-model-g_3d_vel_vector/tf2-model-g/arrays/quiver3D_array31/u.txt", self.u) # BJD 22.4.2021
File "<__array_function__ internals>", line 5, in savetxt
File "/usr/local/lib/python3.8/dist-packages/numpy/lib/npyio.py", line 1371, in savetxt
raise ValueError(
ValueError: Expected 1D or 2D array, got 3D array instead
brendan@DL380pGen8:~/runs/tf2-model-g_3d_vel_vector/tf2-model-g$
I have had to record a 2D quiver plot a while back.
The approach I used, was:
fig
to an image (a numpy array)opencv-python
(cv2
), to write the output.import matplotlib.pyplot as plt
import numpy as np
import io
def fig_to_numpy(fig, dpi=180):
"""
Converts an input Figure, to a numpy array.
If used by Matplotlib, this will close the figure.
:param fig: plt.figure
The input figure, with all items drawn onto it.
:param dpi: int
The resolution of the output image, keep in mind that larger
takes longer.
:return: np.ndarray
Return a numpy array containing the figure images.
"""
buf = io.BytesIO()
fig.tight_layout()
fig.savefig(buf, format="png", dpi=dpi)
plt.close(fig=fig)
buf.seek(0)
img_arr = np.frombuffer(buf.getvalue(), dtype=np.uint8)
buf.close()
img = cv2.imdecode(img_arr, 1)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
return img
This is an example recording class, there are many alternative options (examples).
class Record:
def __init__(self, output, size, fps=20., format='mp4v'):
fourcc = cv2.VideoWriter_fourcc(*format)
self.out = cv2.VideoWriter(output, fourcc, fps, size[::-1])
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
self.close()
def add(self, frame):
if not self.out.isOpened():
raise RuntimeError(f"Video is already closed.")
self.out.write(frame)
def show(self, frame, delay=1):
cv2.imshow('Recording', frame)
cv2.waitKey(delay)
def close(self):
self.out.release()
cv2.destroyWindow('Recording')
This generates a (fake) test image.
def quiver_plot(data, time: int):
""" Create a fake quiver plot. """
fig = plt.figure(figsize=(10, 10))
ax = fig.gca(projection='3d')
ax.set_title("pivot='mid'; every 10th arrow; units='velocity vector' time=" + str(time))
ax.scatter(*data, color='c', s=0)
return fig
def quiver_data(time):
x, y, z = np.meshgrid(np.arange(0.2, 1, 0.2 * time), np.arange(0.2, 1, .2 * time), np.arange(0.2, 1, .8))
u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) * np.sin(np.pi * z))
return u, v, w
Test code
if __name__ == '__main__':
# Get size of figure
data = quiver_data(time=1)
fig = quiver_plot(data, time=1)
arr = fig_to_numpy(fig)
with Record(output='test.mp4', size=arr.shape[:2], fps=1) as writer:
for time in tqdm.trange(1, 11):
data = quiver_data(time)
fig = quiver_plot(data, time)
arr = fig_to_numpy(fig)
writer.add(arr)
writer.show(arr, delay=1)