2013-04-17 12 views
12

Vorrei Matplotlib/Pyplot per generare grafici con una dimensione di tela coerente. Cioè, le figure possono avere dimensioni diverse per adattarsi alle descrizioni degli assi, ma l'area di tracciamento (il rettangolo all'interno del quale vengono disegnate le curve) deve sempre avere le stesse dimensioni.Impostazione della dimensione della tela di stampa in Matplotlib

C'è un modo semplice per raggiungere questo obiettivo? L'opzione figsize di pyplot.figure() sembra impostare la dimensione complessiva della figura, non quella della tela, quindi ottengo una dimensione diversa della tela ogni volta che la descrizione dell'asse occupa più o meno spazio.

+0

È possibile che 'gridspec' ti permetta di controllare ciò che vuoi (vedi gli ultimi 3 [esempi qui] (http://matplotlib.org/examples/pylab_examples/demo_tight_layout.html)). Potresti aggiungere alcuni esempi che mostrano differenti descrizioni degli assi che causano problemi? – Bonlenfum

+0

Questo è un costo del modo in cui MPL decompila la descrizione di cosa disegnare e _how_ per disegnarlo. Abbastanza sicuro di farlo a mano, evitando accuratamente "tight_layout", è il modo migliore per farlo. – tacaswell

risposta

12

Questa è una delle mie più grandi frustrazioni con Matplotlib. Lavoro spesso con dati raster dove ad esempio voglio aggiungere una mappa colori, una legenda e un titolo. Qualsiasi semplice esempio tratto dalla galleria matplotlib comporterà una diversa risoluzione e quindi dati ricampionati. Soprattutto quando si esegue l'analisi delle immagini non si desidera ricampionare (indesiderato).

Ecco cosa faccio di solito, anche se mi piacerebbe sapere se ci sono modi più semplici o migliori.

lascia l'inizio con il caricamento di un'immagine ed emetterlo così come è con la stessa risoluzione:

import matplotlib.pyplot as plt 
import urllib2 

# load the image 
img = plt.imread(urllib2.urlopen('http://upload.wikimedia.org/wikipedia/en/thumb/5/56/Matplotlib_logo.svg/500px-Matplotlib_logo.svg.png')) 

# get the dimensions 
ypixels, xpixels, bands = img.shape 

# get the size in inches 
dpi = 72. 
xinch = xpixels/dpi 
yinch = ypixels/dpi 

# plot and save in the same size as the original 
fig = plt.figure(figsize=(xinch,yinch)) 

ax = plt.axes([0., 0., 1., 1.], frameon=False, xticks=[],yticks=[]) 
ax.imshow(img, interpolation='none') 

plt.savefig('D:\\mpl_logo.png', dpi=dpi, transparent=True) 

noti che i definita manualmente la posizione degli assi in modo che abbraccia l'intera figura.

In modo simile a quanto sopra si potrebbe aggiungere un certo margine intorno all'immagine per consentire etichette o colorbars ecc

questo esempio viene aggiunto un margine del 20% sopra l'immagine, che viene poi utilizzato per il tracciato di un titolo:

fig = plt.figure(figsize=(xinch,yinch/.8)) 

ax = plt.axes([0., 0., 1., .8], frameon=False, xticks=[],yticks=[]) 
ax.imshow(img, interpolation='none') 
ax.set_title('Matplotlib is fun!', size=16, weight='bold') 

plt.savefig('D:\\mpl_logo_with_title.png', dpi=dpi) 

Così la figura y-size (altezza) viene aumentata e la dimensione y degli assi è diminuita in modo uguale. Ciò fornisce un'immagine di output (generale) più ampia, ma l'area degli assi avrà ancora le stesse dimensioni.

Potrebbe essere bello avere una proprietà di figura o di assi come .set_scale() per forzare un vero output 1-su-x.

+0

È possibile utilizzare invece un formato vettoriale? _should_ (penso) disegna ogni pixel come un rettangolo. O solo _ via_ sul campione. – tacaswell

+2

Grazie, il tuo suggerimento ha funzionato! A proposito, penso di aver trovato un modo leggermente più elegante usando subplot_adjust (0,0,1,1) immediatamente dopo aver chiamato figure(). Quindi, non è necessario definire le posizioni degli assi perché sono già grandi come la figura. Infine, puoi chiamare savefig() con l'argomento bbox_inches = 'tight' se non vuoi specificare manualmente i margini. In questo caso, l'area di tracciamento sarà esattamente come definita da (xinch, yinch) e la figura sarà abbastanza grande da contenere le descrizioni degli assi. (Come sottolineato da tcaswell, non usare tight_layout!) – Dario

+0

Sembra davvero più facile, grazie per i suggerimenti. Proverò i tuoi suggerimenti più tardi. @tcaswell, grazie, potrebbe funzionare in alcune situazioni, penso che pcolor dovrebbe essere in grado di farlo abbastanza facilmente. Qualsiasi altra post-elaborazione sarebbe più difficile però. –

Problemi correlati