I've been looking around for answers but I can't seem to see why in my code I can't get the projected contours to show up "behind" the surface.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.array([[200,800,1500,2000,3000],[200,700,1500,2000,3000],[200,800,1500,2000,3000],[200,800,1500,2000,3000]])
Y = np.array([[50,50,50,50,50],[350,350,350,350,350],[500,500,500,500,500],[1000,1000,1000,1000,1000]])
Z = np.array([[0,0,33,64,71],[44,62,69,74,76],[59,67,72,75,77],[63,68,73,76,77]])
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, alpha=0.5)
cset = ax.contourf(X, Y, Z, zdir='z', offset=0, cmap=cm.coolwarm)
cset = ax.contourf(X, Y, Z, zdir='x', offset=200, cmap=cm.coolwarm)
cset = ax.contourf(X, Y, Z, zdir='y', offset=1000, cmap=cm.coolwarm)
ax.set_xlabel('X')
ax.set_xlim(200, 3000)
ax.set_ylabel('Y')
ax.set_ylim(0, 1000)
ax.set_zlabel('Z')
ax.set_zlim(0, 100)
plt.show()
I have been using the one of the Filled Contour Plots from this page as template: http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#scatter-plots
At the moment the best I could get was to change the alpha value of the contours. I also tried plotting the surface after the contours but that didn't change anything.
Any advice would be most welcome !
The problem you're experiencing is a well-known bug/missing feature in matplotlib. Quoting a co-lead developer of matplotlib:
As I understand it all the 3D plotting as a bit of a hack.
The issue boils down to that contiguous blocks of surfaces are plotted one after the other, such that each is either fully behind any other, or fully in front of it. This will imply that any two objects are drawn properly only from certain angles, and there's no guarantee that all objects will be drawn with the proper order at reasonable angles of interest.
One would think that setting zorder
properties for the various objects could affect the result, but this is not the case, since
splitting up the plotting is that 'above' and 'below' are determined in a some what arcane way
in other words
Axes3D ignores zorder and draws artists in the order it thinks they should be.
This manifests itself in all sorts of 3d plots, such as when plotting text with surfaces, plotting complicated surfaces, or even plotting 3d bar plots (even though one could expect that it's easier to determine the plotting order within a single function call).
For surfaces plotted with a single command (i.e. those that comprise a single Poly3DCollection
) you can use the set_zsort()
method to give a very crude hint to matplotlib regarding the preferred plotting order. Other than this, your only option is moving your surfaces and viewing angles around (if at all possible) in a way that the issue is not visible, or at least not entirely apparent. Another option proposed by @tcaswell is to use mayavi instead of mplot3d (but I've never done that myself).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With