I am trying to ‘paint’ the faces of a cube with a contourf function using Python Matplotlib. Is this possible?
This is similar idea to what was done here but obviously I cannot use patches. Similarly, I don’t think I can use add_collection3d like this as it only supports PolyCollection, LineColleciton and PatchCollection.
I have been trying to use contourf on a fig.gca(projection='3d')
. Toy example below.
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np plt.close('all') fig = plt.figure() ax = fig.gca(projection='3d') ############################################ # plotting the 'top' layer works okay... # ############################################ X = np.linspace(-5, 5, 43) Y = np.linspace(-5, 5, 28) X, Y = np.meshgrid(X, Y) varone=np.random.rand(75,28,43) Z=varone[0,:,:] cset = ax.contourf(X, Y, Z, zdir='z', offset=1, levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') #see [1] plt.show() ################################################# # but now trying to plot a vertical slice.... # ################################################# plt.close('all') fig = plt.figure() ax = fig.gca(projection='3d') Z=varone[::-1,:,-1] X = np.linspace(-5, 5, 28) Y = np.linspace(-5, 5, 75) X, Y = np.meshgrid(X, Y) #this 'projection' doesn't result in what I want, I really just want to rotate it cset = ax.contourf(X, Y, Z, offset=5,zdir='x', levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') #here's what it should look like.... ax=fig.add_subplot(1, 2,1) cs1=ax.contourf(X,Y,Z,levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') #see [2] plt.show()
1 From the example, the top surface comes easily:
2 But I’m not sure how to do the sides. Left side of this plot is what the section should look like (but rotated)…
Open to other python approaches. The data I’m actually plotting are geophysical netcdf files.
Advertisement
Answer
You have to assign the data to the right axis. The zig-zag results from the fact that now you are at x = const
and have your oscillation in the z
-direction (from the random data, which is generated between 0
and 1
).
If you you assign the matrixes differently in your example, you end up with the desired result:
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np plt.close('all') fig = plt.figure() ax = fig.gca(projection='3d') X = np.linspace(-5, 5, 43) Y = np.linspace(-5, 5, 28) X, Y = np.meshgrid(X, Y) varone=np.random.rand(75,28,43) * 5.0 - 10.0 Z=varone[0,:,:] cset = [[],[],[]] # this is the example that worked for you: cset[0] = ax.contourf(X, Y, Z, zdir='z', offset=5, levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') # now, for the x-constant face, assign the contour to the x-plot-variable: cset[1] = ax.contourf(Z, Y, X, zdir='x', offset=5, levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') # likewise, for the y-constant face, assign the contour to the y-plot-variable: cset[2] = ax.contourf(X, Z, Y, zdir='y', offset=-5, levels=np.linspace(np.min(Z),np.max(Z),30),cmap='jet') # setting 3D-axis-limits: ax.set_xlim3d(-5,5) ax.set_ylim3d(-5,5) ax.set_zlim3d(-5,5) plt.show()
The result looks like this: