Black lines when saving 3D surface to pdf: how can I get rid of them?
I have the following code to render 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 plot display in Spyder is "correct", but the PDF seems to be ignoring linewidth=0.
. How can I fix this?
Spyder output:
PDF output:
source to share
matplotlib github thinks this is fixed, but that the fix did not make it to v1.4.1 but will be posted to v1.4.3 https://github.com/matplotlib/matplotlib/issues/2247
source to share
As others have pointed out, this is due to a bug in the pdf file that needs to be resolved in the newest version of matplotlib.
This is a hack / workaround to get slightly better results in older versions too. You can explicitly set the transparency of edgecolor:
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:
EDIT:
As pointed out in the comments, using the keyword alpha
overwrites the alpha value of the edge color. Thus, we must explicitly define the transparency for the complexions. The easiest way I can see is to adapt the color code:
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:
source to share