I have extracted nodal fields from my geodynamic simulation, but I'm stuck on visualizing it. Here I take rock density rho
[kg/m3] as an example. The data are represented on the nodal points of a 3D rectangular grid, with a resolution of 10 * 3 * 10 km.
The lengths of my coordinates are X * Y * Z = 213 * 69 * 133 nodes, where X and Z are horizontal and Y is the vertical coordinate. The dimensions of rho
are 69 * 213 * 133 (so y, x, z)
Ideally, I would like to draw some sort of box in (x,z,y) space and assign a color to it according to the value of rho
. However, for now I'm fine with creating a color-coded scatter plot at the nodes. I've looked in many places, e.g. the matplotlib.mpl_toolkits.Axes3D documentation, and here, and almost all of them say something like
img = ax.scatter(x, z, y, c=rho, cmap=plt.hot())
Or versions using ax.plot_surface
, or ax.plot_trisurf
, and those explicitly require X, Y, Z to be of the same length.
ax.scatter
also only seems to work when x, y, z and rho have the same length, which seems unnecessary to me... However I try, I get errors like (on calling the scatter command):
File "/usr/lib/python3/dist-packages/mpl_toolkits/mplot3d/axes3d.py", line 2354, in scatter
xs, ys, zs = np.broadcast_arrays(
File "<__array_function__ internals>", line 5, in broadcast_arrays
File "/usr/lib/python3/dist-packages/numpy/lib/stride_tricks.py", line 264, in broadcast_arrays
shape = _broadcast_shape(*args)
File "/usr/lib/python3/dist-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
I looked up what that means, and supposedly it means that the dimensions don't match. But I checked in a debugger, and the dimensions are correct.
I tried flattening rho
(same result) and I tried looping over each node and plotting each point separately (sample down below)
rho, x, y, z = read_data('/path/to/my/data')
fig = plt.figure()
ax = fig.add_subplot(1,1,1, projection='3d')
for i in range(len(x)):
for j in range(len(z)):
for k in range(len(y)):
ax.scatter(x[i], z[j], y[k], c=ronew[k, i, j], cmap='hot')
cbar = plt.colorbar(orientation='horizontal')
cbar.set_label('Density [kg/m3]')
plt.xlabel("X [km]")
plt.ylabel("Z [km]")
plt.zlabel("Depth [km]")
plt.show()
I imagine I'm not the only one who needs to make these "4D" figures. Therefore, any help would be very much appreciated! To make helping easier, here's a sample data that produces the above copied error:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
x = np.arange(0, 10)
y = np.arange(0, 6)
z = np.arange(0, 20)
rho = np.random.randint(1000, 3500, (10, 6, 20))
fig = plt.figure()
print(x.shape, y.shape, z.shape, rho.shape)
ax = fig.add_subplot(projection='3d')
ax.scatter(x, y, z, c=rho, cmap='hot')
plt.show()