I am making a 3d plot with matplotlib with 2 surfaces (see example below). So far both surfaces get their own colormap, being blue in the bottom and yellow on top.
However, I want a single colormap for both surfaces, i.e. the very bottom is blue, the very top is yellow and the touching point of both surfaces is green.
How can I achieve that? Do I need to somehow combine both surfaces before plotting, or do I need to restrict the colormaps of both surfaces (lower from blue to green, upper from green to yellow)?
Thanks for your help.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
ky = np.linspace(-np.pi*2/3,np.pi*2/3,100)
kz = np.linspace(-np.pi*2/3,np.pi*2/3,100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
KY, KZ = np.meshgrid(ky, kz)
E = np.cos(KY)*np.cos(KZ)
ax.plot_surface(KY, KZ, E-1, rstride=1, cstride=1, cmap=cm.viridis) #surface 1
ax.plot_surface(KY, KZ, -E+1, rstride=1, cstride=1, cmap=cm.viridis) #surface 2
ax.view_init(elev=7, azim=-69)
plt.show()
You can explicitly set vmin
and vmax
for a colormap to force the range for the colors.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
ky = np.linspace(-np.pi*2/3,np.pi*2/3,100)
kz = np.linspace(-np.pi*2/3,np.pi*2/3,100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
KY, KZ = np.meshgrid(ky, kz)
E = np.cos(KY)*np.cos(KZ)
ax.plot_surface(KY, KZ, E-1, rstride=1, cstride=1, cmap=cm.viridis, vmin=-2, vmax=2) #surface 1
ax.plot_surface(KY, KZ, -E+1, rstride=1, cstride=1, cmap=cm.viridis, vmin=-2, vmax=2) #surface 2
ax.view_init(elev=7, azim=-69)
plt.show()
To make the range tight against actual Z values in your two surfaces, you can use
vmin=np.amin(E-1), vmax=np.amax(-E+1)
You could also create this effect by defining your own color maps that go from yellow to green at the top, and from green to blue at the bottom.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from matplotlib import cm
from matplotlib.colors import ListedColormap
ky = np.linspace(-np.pi*2/3,np.pi*2/3,100)
kz = np.linspace(-np.pi*2/3,np.pi*2/3,100)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
KY, KZ = np.meshgrid(ky, kz)
E = np.cos(KY)*np.cos(KZ)
viridis = cm.get_cmap('viridis', 512)
topcolors = viridis(np.linspace(0.5, 1, 256))
topcm = ListedColormap(topcolors)
bottomcolors = viridis(np.linspace(0, 0.5, 256))
bottomcm = ListedColormap(bottomcolors)
ax.plot_surface(KY, KZ, E-1, rstride=1, cstride=1, cmap=bottomcm) #surface 1
ax.plot_surface(KY, KZ, -E+1, rstride=1, cstride=1, cmap=topcm) #surface 2
ax.view_init(elev=7, azim=-69)
plt.show()