Reputation: 1602
I have a 3D plot which looks quite similar to this one , but I want to add two lines drawn on the bottom contour plot. I would like the two lines to cross at and point to a particular (x,y) value.
I can draw a line there but it is always beneath the contour plot, despite my numerous attempts. Can anyone help me drawing the line on the contour plot? I am pasting my code below. The line is visible only in the part where it sticks out from the contour.
#!/usr/bin/env python
import sys, re, math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import LineCollection
from matplotlib import cm
from matplotlib.mlab import griddata
import numpy as np
x = []
y = []
z = []
for i in range(0,628,10) :
for j in range(0,628,10) :
x.append(i*0.01)
y.append(j*0.01)
z.append(math.sin(x[-1]*y[-1])*20)
fig = plt.figure()
ax = fig.gca(projection='3d')
xi = np.linspace(min(x), max(x))
yi = np.linspace(min(y), max(y))
X, Y = np.meshgrid(xi, yi)
Z = griddata(x, y, z, xi, yi)
ax.autoscale(False)
ax.view_init(elev=30, azim=-140)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.cool,
linewidth=0.1, antialiased=True, shade=True,alpha=0.8)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.cool, cstride=1,
linewidth=0.1, antialiased=True, shade=True)
ax.set_xlim3d(0, math.pi*2)
ax.set_ylim3d(0, math.pi*2)
ax.set_zlim3d(-100, 20)
xi = [0,6]
yi = [3,3]
l=zip(xi,yi)
lines = LineCollection((l,l),zorder=10000,color='k')
ax.add_collection3d(lines,zs=-90)
plt.show()
Upvotes: 4
Views: 8260
Reputation: 31
The answer from HYRY helped me. Since tnorgd wants to know how to do it for a scatter plot (and I cannot comment yet) I give the answer here. A pyplot.scatter creates a Patch3DCollection in projection "3d". So the same trick will work:
from mpl_toolkits.mplot3d.art3d import Patch3DCollection
class FixZorderScatter(Patch3DCollection):
_zorder = 2000
@property
def zorder(self):
return self._zorder
@zorder.setter
def zorder(self, value):
pass
Upvotes: 3
Reputation: 97261
Because Axe3D will calculate the zorder
attribute for every 3d object by 3d projection. To disable this you can create a FixZorderCollection
class and change the 3d line's __class__
attribute. Here is a full example:
import sys, re, math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import LineCollection
from matplotlib import cm
from matplotlib.mlab import griddata
import numpy as np
x = []
y = []
z = []
for i in range(0,628,10) :
for j in range(0,628,10) :
x.append(i*0.01)
y.append(j*0.01)
z.append(math.sin(x[-1]*y[-1])*20)
fig = plt.figure()
ax = fig.gca(projection='3d')
xi = np.linspace(min(x), max(x))
yi = np.linspace(min(y), max(y))
X, Y = np.meshgrid(xi, yi)
Z = griddata(x, y, z, xi, yi)
ax.autoscale(False)
ax.view_init(elev=30, azim=-140)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.cool,
linewidth=0.1, antialiased=True, shade=True,alpha=0.8)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.cool, cstride=1,
linewidth=0.1, antialiased=True, shade=True)
ax.set_xlim3d(0, math.pi*2)
ax.set_ylim3d(0, math.pi*2)
ax.set_zlim3d(-100, 20)
xi = [0,6]
yi = [3,3]
l=zip(xi,yi)
lines = LineCollection((l,l),zorder=1000,color='k',lw=3)
ax.add_collection3d(lines,zs=-90)
from mpl_toolkits.mplot3d.art3d import Line3DCollection
class FixZorderCollection(Line3DCollection):
_zorder = 1000
@property
def zorder(self):
return self._zorder
@zorder.setter
def zorder(self, value):
pass
ax.collections[-1].__class__ = FixZorderCollection
plt.show()
output:
Upvotes: 4