I am plotting a surface with bunch of polygons. The plotting is quite simple as shown below.
def plotSurface(cell, numOfLayer, name=None, alpha = 0.5):
#
The figure margins can be reduced by setting fig.subplots_adjust(top=1, bottom=0, left=0, right=1)
. This might or might not be sufficient, depending on the actual figure.
Also mind that if the axes aspect is set to equal, the figsize
must be squared. (This is not the case here, but might be needed for other cases).
The last knob to turn would be to reduce the axis limits. Those can be set to smaller values to reduce the white space around the object.
For example, plotting a sphere with radius 1 around the origin, one would be tempted to set the limits to [-1,1]
to fit the whole sphere into the plot. However, this will leave a lot of white space around. Reducing the limits to [-0.57,0.57]
will let the sphere fit nicely into the figure. To see this effect, I left the axes turned on in the example below.
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
u = np.linspace(0, 2 * np.pi, 12)
v = np.linspace(0, np.pi,15)
x = np.outer(np.cos(u), np.sin(v))
y = np.outer(np.sin(u), np.sin(v))
z = np.outer(np.ones(np.size(u)), np.cos(v))
F = np.sin(x)*y + z
F = (F-F.min())/(F-F.min()).max()
#Set colours and render
fig = plt.figure(figsize=(8,4))
fig.subplots_adjust(top=1, bottom=0, left=0, right=1, wspace=0)
ax = fig.add_subplot(121, projection='3d')
ax2 = fig.add_subplot(122, projection='3d')
# plotting a sphere with radius 1.
# Naturally, setting the limits to 1 makes sense
ax.plot_surface(x,y,z, rstride=1, cstride=1, facecolors=cm.jet(F), alpha=0.5)
ax.set_xlim(np.array([-1,1]))
ax.set_ylim(np.array([-1,1]))
ax.set_zlim(np.array([-1,1]))
# plotting a sphere with radius 1.
# but now reducing the limits
ax2.plot_surface(x,y,z, rstride=1, cstride=1, facecolors=cm.jet(1-F), alpha=0.5)
ax2.set_xlim(np.array([-1,1])*.57)
ax2.set_ylim(np.array([-1,1])*.57)
ax2.set_zlim(np.array([-1,1])*.57)
#ax.axis('off') # turned on to see the effect. Turn off to have a nice image.
plt.show()
Several ways you can modify the whitespace:
Reduce the whitespace inside the axes. To do this, you could modify the x
, y
and z
limits using:
ax.set_xlim()
ax.set_ylim()
ax.set_zlim()
Reduce the whitespace outside the axes. To do this, you can use:
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
Finally, you could just save a portion of the figure when you call savefig
. You can modify this area using the bbox_inches
kwarg, by using an actual Bbox
rather than setting it to tight
.
For example, lets consider this image from the matplotlib gallery. Note that I've change the axis and figure background colours, so they show up clearly on the page below.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(10,8))
# I added a pink axis background, just so its easy to see against the white page
ax = fig.add_subplot(111, projection='3d', axisbg='#FFAAAA')
u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)
x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, rstride=4, cstride=4, color='b')
ax.axis('off')
# Save the original figure (using a grey background for the figure for clarity)
plt.savefig('3d_whitespace0.png', facecolor='#AAAAAA')
# Step 1 above: change the axes limits
ax.set_xlim(-8, 8)
ax.set_ylim(-8, 8)
ax.set_zlim(-8, 8)
plt.savefig('3d_whitespace1.png', facecolor='#AAAAAA')
# Step 2 above: change the subplot margins
fig.subplots_adjust(left=0, right=1, bottom=0, top=1)
plt.savefig('3d_whitespace2.png', facecolor='#AAAAAA')
# Step 3 above: save only a portion of the figure. Here we will cut one inch
# off each side of the figure, to change the 10in x 8in figure to 8in x 6in
bbox = fig.bbox_inches.from_bounds(1, 1, 8, 6)
plt.savefig('3d_whitespace3.png', bbox_inches=bbox, facecolor='#AAAAAA')