3

I have the following code to display a 3D surface using ax.plot_surface:

fig = plt.figure()
ax  = fig.gca(projection='3d')
X,Y = np.meshgrid(range(k_mean.shape[0]), range(k_mean.shape[1])) 
Z   = k_mean
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0., alpha=0.8, cmap=cm.nipy_spectral, antialiased=False, shade=False)
cset = ax.contour(X, Y, Z, zdir='z', offset=0, cmap=cm.nipy_spectral)
cset = ax.contour(X, Y, Z, zdir='x', offset=0, cmap=cm.nipy_spectral)
cset = ax.contour(X, Y, Z, zdir='y', offset=120, cmap=cm.nipy_spectral)

ax.set_xlim(0, 120)
ax.set_ylim(0, 120)
ax.set_zlim(0, 1)

fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
plt.savefig('3d.pdf', dpi=500)

The display of the plot in Spyder is "correct", but the PDF seems to ignore the linewidth=0.. How can I fix that?

Spyder output: Spyder output

PDF output: PDF output

user3017048
  • 2,711
  • 3
  • 22
  • 32

2 Answers2

3

matplotlib github think this is fixed but that the fix didn't make it into v1.4.1 but will be put in v1.4.3 https://github.com/matplotlib/matplotlib/issues/2247

paddyg
  • 2,153
  • 20
  • 24
3

As others have pointed out, this is related to a bug in the pdf backend, which should be resolved in the newest version of matplotlib.

This is hack / workaround to get slightly more appealing results also in older versions. You can set the edgecolor explicitly to fully transparent:

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
        linewidth=0, antialiased=True, edgecolor=(0,0,0,0))

Results for comparison: enter image description here enter image description here

EDIT:

As pointed out in the comments, using the alpha keyword overwrites the alpha value of the edge color. Thus, we need to define transparency for the face colors explicitly. The simplest way I can see, is to adapt the colormap:

from matplotlib.colors import LinearSegmentedColormap

colors = np.array(cm.coolwarm(np.linspace(0,1,256)))
colors[:,3] = 0.6
cmap = LinearSegmentedColormap.from_list('alpha_cmap', colors.tolist())

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cmap,
        linewidth=0, antialiased=True, edgecolor=(0,0,0,0))

Result: enter image description here

hitzg
  • 12,133
  • 52
  • 54
  • 1
    In case anyone tries this (which seems to work): as well as setting edgecolor, this fix needs to exclude the alpha keyword argument - even apha=1.0 seems to stop it working. – paddyg Apr 23 '15 at 14:01
  • Good point. The `alpha` keyword overwrites color specific alpha values in (almost?) all matplotlib functions. – hitzg Apr 23 '15 at 14:03
  • @paddyg I added an example of how to add transparency to the face colors. – hitzg Apr 23 '15 at 14:15