2011-11-17 7 views
5

Desidero generare automaticamente una serie di grafici che vengono ritagliati sulle patch. Se provo a riutilizzare un oggetto patch, sposta la posizione sul canvas.Riutilizzo degli oggetti patch in Matplotlib senza che si spostino posizione

Questo script (basato su una risposta a una domanda precedente di Yann) dimostra cosa sta succedendo.

import pylab as plt 
import scipy as sp 
import matplotlib.patches as patches 

sp.random.seed(100) 
x = sp.random.random(100) 
y = sp.random.random(100) 
patch = patches.Circle((.75,.75),radius=.25,fc='none') 


def doplot(x,y,patch,count): 
    fig = plt.figure() 
    ax = fig.add_subplot(111) 
    im = ax.scatter(x,y) 
    ax.add_patch(patch) 
    im.set_clip_path(patch) 
    plt.savefig(str(count) + '.png') 


for count in xrange(4): 
    doplot(x,y,patch,count) 

La prima trama assomiglia a questo: Correct position of patch - first time plotted

Ma nel secondo '1.png', la patch è spostato .. Wrong position of the patch

Tuttavia tracciare nuovamente ancora non si muove la patch . '2.png' e '3.png' hanno lo stesso aspetto di '1.png'.

Qualcuno potrebbe indicarmi la direzione giusta di ciò che sto facendo male ??

In realtà, le patch che sto utilizzando sono relativamente complesse e richiedono un po 'di tempo per generare: preferirei non doverle rifare ogni frame se possibile.

+1

La parte veramente bizzarra è che ciò accade solo se si chiama 'savefig', e non se si chiama' show' ... –

risposta

2

Il problema può essere evitato utilizzando gli stessi assi per ciascun grafico, con ax.cla() chiamato per cancellare il grafico dopo ogni iterazione.

import pylab as plt 
import scipy as sp 
import matplotlib.patches as patches 

sp.random.seed(100) 
patch = patches.Circle((.75,.75),radius=.25,fc='none') 

fig = plt.figure() 
ax = fig.add_subplot(111) 

def doplot(x,y,patch,count): 
    ax.set_xlim(-0.2,1.2) 
    ax.set_ylim(-0.2,1.2) 
    x = sp.random.random(100) 
    y = sp.random.random(100) 
    im = ax.scatter(x,y) 
    ax.add_patch(patch) 
    im.set_clip_path(patch) 
    plt.savefig(str(count) + '.png') 
    ax.cla() 

for count in xrange(4): 
    doplot(x,y,patch,count) 
+0

Grazie @unutbu! Funziona perfettamente. –

+0

Grande; felice di poterti aiutare! Per favore non accettare questa risposta, perché mi piacerebbe sapere perché la patch viene trasformata anche nel tuo codice originale. – unutbu

2

Un'alternativa alla risposta di unutbu, è quello di utilizzare il pacchetto copy, che può copiare gli oggetti. È molto difficile vedere come cambiano le cose dopo una chiamata add_patch, ma lo sono. Sono modificate le proprietà axes, figure, extents, clip_box, transform e window_extent. Sfortunatamente la stampa superficiale di ciascuna di queste proprietà ha come risultato la stessa stringa, quindi sembra che non stiano cambiando. Ma gli attributi sottostanti di alcune o tutte queste proprietà, ad esempio extents, sono un Bbox, probabilmente sono state modificate.

La chiamata di copia consentirà di ottenere una patch univoca per ogni figura creata, senza sapere che tipo di patch è. Questo ancora non risponde perché questo accade, ma come ho scritto sopra è una soluzione alternativa al problema:

import copy 

def doplot(x,y,patch,count): 
    newPatch = copy.copy(patch) 
    fig = plt.figure(dpi=50) 
    ax = fig.add_subplot(111) 
    im = ax.scatter(x,y) 
    ax.add_patch(newPatch) 
    im.set_clip_path(newPatch) 
    plt.savefig(str(count) + '.png') 

Inoltre è possibile utilizzare fig.savefig(str(count) + '.png'). Ciò salva esplicitamente la figura fig dove la chiamata plt.savefig salva la figura corrente, che è quella che si desidera.

Problemi correlati