2015-08-08 20 views
14

Ecco un esempio barebone:Come ritagliare un grafico di Axes3D con proporzioni quadrate?

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() 

Questo è ciò che ottengo:

square viewports

Questo è quello che voglio:

rectangular viewports

In altre parole, voglio i grafici stessi hanno un rapporto di aspetto quadrato, non tutti estesi in questo modo:

stretched out

ed ho ottenuto la parte grazie al lavoro per https://stackoverflow.com/a/31364297/125507

ma voglio le finestre che in quei complotti per essere rettangolare, con la parte superiore e inferiore tagliate fuori (dal momento che non ci sarà solo spazio bianco in alto e in basso e sto generando più GIF animate quindi non posso facilmente post-elaborarlo nella forma che voglio).

Fondamentalmente sto facendo questa animazione, e voglio la stessa cosa, ma senza tutti gli spazi:

animation

+0

Non sto usre tuo esempio è abbastanza rappresentativa, hai provato ' fig.subplots_adjust (top = 1, bottom = 0, right = 1, left = 0, hspace = 0, wspace = 0) '? – rll

+0

Oltre a ciò, è necessario stringere il 'r' – rll

+0

@rll Sì, ho accorciato un asse da quello che effettivamente desidero, per illustrare che sono tutti della stessa lunghezza – endolith

risposta

3

Al fine di follow-up su miei commenti e mostrano esempi da settting un piccoli r e rimozione margini sottotrama utilizzando 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() 

Questo darà sottotrame più stretti, come le impostazioni predefinite per SubplotParams sono i seguenti:

sinistra: 0.125

destra: 0.9

fondo: 0.1

superiore: 0,9

wspace : 0.2

hspace: 0,2

non sono sicuro che sia questo il PO è alla ricerca di se ...

enter image description here

+0

ogni trama è ancora quadrata, tuttavia, voglio renderli rettangoli pur avendo gli stessi assi – endolith

-1

Dal momento che si desidera lotto rettangolare, non è possibile utilizzare set_aspect('equal'), invece è necessario regolare i limiti della vostra piazzole tenere conto della differenza di proporzioni.

Nel tentativo di sotto, Ho usato il bbox dell'asse per ottenere il height e width degli assi e usato il rapporto di aspetto riscalare X e Y assi.(Supponevo che entrambi i grafici abbiano la stessa dimensione, ma potresti anche avere grafici con dimensioni diverse, dovrai solo regolare i limiti degli assi in modo indipendente per ognuno di essi).

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() 
# Cannot use 'equal' aspect for a rectangular plot 
# f.set_aspect('equal') 
# t.set_aspect('equal') 

# get the dimensions of the axes from its bbox 
f_bbox = f.get_position() 
f_height = f_bbox.height 
f_width = f_bbox.width 


r = 6 
f.set_xlim3d([-1 * f_width/f_height * r, f_width/f_height * r]) 
f.set_ylim3d([-1 * f_width/f_height * r, f_width/f_height * r]) 
f.set_zlim3d([-r, r]) 

t.set_xlim3d([-1 * f_width/f_height * r, f_width/f_height * r]) 
t.set_ylim3d([-1 * f_width/f_height * r, f_width/f_height * r]) 
t.set_zlim3d([-r, r]) 

f.set_axis_off() 
t.set_axis_off() 

plt.draw() 
plt.show() 

Nota: In questa foto, ho aggiunto un colore di sfondo per evidenziare la forma rettangolare delle trame

+0

non mantengono le proporzioni quando ruotati però. il viewport deve essere ritagliato in un rettangolo, non ristretto in uno solo – endolith