Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I crop an Axes3D plot with square aspect ratio?

Tags:

Here's a barebones example:

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

fig = plt.figure()
f = fig.add_subplot(2, 1, 1, projection='3d')
t = fig.add_subplot(2, 1, 2, projection='3d')

# axes
for d in {f, t}:
    d.plot([-1, 1], [0, 0], [0, 0], color='k', alpha=0.8, lw=2)
    d.plot([0, 0], [-1, 1], [0, 0], color='k', alpha=0.8, lw=2)
    d.plot([0, 0], [0, 0], [-1, 1], color='k', alpha=0.8, lw=2)

f.dist = t.dist = 5.2   # 10 is default

plt.tight_layout()
f.set_aspect('equal')
t.set_aspect('equal')

r = 6
f.set_xlim3d([-r, r])
f.set_ylim3d([-r, r])
f.set_zlim3d([-r, r])

t.set_xlim3d([-r, r])
t.set_ylim3d([-r, r])
t.set_zlim3d([-r, r])

f.set_axis_off()
t.set_axis_off()

plt.draw()
plt.show()

This is what I get:

square viewports

This is what I want:

rectangular viewports

In other words, I want the plots themselves to have a square aspect ratio, not all stretched out like this:

stretched out

and I got that part working thanks to https://stackoverflow.com/a/31364297/125507

but I want the windows looking into those plots to be rectangular, with the top and bottom cropped out (since there will just be white space on top and bottom and I'm generating multiple animated GIFs so I can't easily post-process it to the shape I want).

Basically I am making this animation, and I want the same thing but without all the whitespace:

animation

like image 643
endolith Avatar asked Aug 08 '15 01:08

endolith


1 Answers

In order to follow up on my comments and show examples by settting a smaller r and removing subplot margins using subplots_adjust:

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

fig = plt.figure()
f = fig.add_subplot(2, 1, 1, projection='3d')
t = fig.add_subplot(2, 1, 2, projection='3d')

# axes
for d in {f, t}:
    d.plot([-1, 1], [0, 0], [0, 0], color='k', alpha=0.8, lw=2)
    d.plot([0, 0], [-1, 1], [0, 0], color='k', alpha=0.8, lw=2)
    d.plot([0, 0], [0, 0], [-1, 1], color='k', alpha=0.8, lw=2)

f.dist = t.dist = 5.2   # 10 is default

plt.tight_layout()
f.set_aspect('equal')
t.set_aspect('equal')

r = 1
f.set_xlim3d([-r, r])
f.set_ylim3d([-r, r])
f.set_zlim3d([-r, r])

t.set_xlim3d([-r, r])
t.set_ylim3d([-r, r])
t.set_zlim3d([-r, r])

f.set_axis_off()
t.set_axis_off()

fig.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)

plt.draw()
plt.show()

This will give tighter subplots, as the defaults for SubplotParams are as follows:

left : 0.125

right : 0.9

bottom : 0.1

top : 0.9

wspace : 0.2

hspace : 0.2

not sure it is this the OP is looking for though...

enter image description here

like image 91
rll Avatar answered Oct 03 '22 21:10

rll