PepeToro
PepeToro

Reputation: 559

Plot a surface with duplicated data

I want to plot a cut off surface and save in pdf format.

I am plotting surfaces which satisfy certain equations. In order to have more "beautiful" pictures I am "cutting" parts off the surface that go out of the plot bounds. I do this basically by mapping the points outside the bounds to points in the boundary, so I produce repeated data in the corresponding arrays. When I try to save this surfaces in .pdf format (which is what I would like) I receive the following error:

Can only output finite numbers in PDF

I am assuming this error comes precisely from matplotlib when trying to generate a surface between equal points. But, I can save in .png, which I don't like. Is there a workaround for this? here I include a commented and working example.

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

#Set the size of the figures and some parameters
f_width=2.5 
f_height=((np.sqrt(5)-1)/2)*f_width  
fig_size =  [f_width,f_height]
fig = plt.figure(num=1, figsize=fig_size);

ax  = Axes3D(fig)

### --- CREATE THE MESH --- ###
x   = np.linspace(-2,2.0,50)
b   = np.linspace(-3,3,50)
B,X = np.meshgrid(b,x)
### ---------------------- ###

### --- CREATE SURFACE --- ###
a = -2
C = -X**4 - a*X**2 - B*X
    ### ---------------------- ###

r,c = np.shape(C)
## -- CUT THE SURFACE .. comment all this for the uncut version -- ##
for j in range(r):
    for k in range(c):
        if C[j][k]<-2 and X[j][k]>0:
            C[j][k] =-2
            roots   = np.roots([1,0,a,B[j][k],C[j][k] ])
            roots   = roots[roots.imag==0]
            X[j][k] = np.real(roots[roots.real>0])

        if C[j][k]<-2 and X[j][k]<0:
            C[j][k] = -2
            roots   = np.roots([1,0,a,B[j][k],C[j][k] ])
            roots   = roots[roots.imag==0]
            X[j][k] = np.real(roots[roots.real<0])
## ------------------------- end of cut -------------------------- ##

## -- PLOT THE SURFACE -- ##
ax.plot_surface(C,B,X,rstride = 1, alpha=0.5 , 
    cstride = 1, color = '0.5',linewidth = 0., 
    antialiased = True,zorder=0.5)

### --- CONFIGURE AXES --- ###
ax.xaxis.set_ticks([])
ax.yaxis.set_ticks([])
ax.zaxis.set_ticks([])
ax.set_xlim3d(-2, 4)
ax.set_ylim3d(-3,3)
ax.set_zlim3d(-3,2)
ax.set_xlabel(r'$c$')
ax.set_ylabel(r'$b$')
ax.set_zlabel(r'$x$')
ax.view_init(15,15)
### ---------------------- ###
#plt.savefig('figure.pdf')
plt.savefig('figure.png',dpi=300)

Upvotes: 2

Views: 544

Answers (1)

HYRY
HYRY

Reputation: 97301

You can modify the result of X at the cut edges by some random noise. Add the following two lines before ax.plot_surface:

mask = C == -2
X[mask] += np.random.normal(scale=1e-5, size=np.sum(mask))

Upvotes: 1

Related Questions