2011-11-17 12 views
5

Chcę automatycznie wygenerować serię wykresów, które są przypięte do łatek. Jeśli spróbuję ponownie użyć obiektu patcha, przesunie on pozycję na płótnie.Ponowne użycie obiektów patcha w matplotlib bez ich przemieszczania się

Ten skrypt (oparty na odpowiedzi na poprzednie pytanie Yanna) pokazuje, co się dzieje.

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) 

Pierwsza działka wygląda tak: Correct position of patch - first time plotted

Ale w drugim „1.png” plaster został przeniesiony .. Wrong position of the patch

Jednak replotting znowu nie porusza poprawkę . "2.png" i "3.png" wyglądają dokładnie tak samo jak "1.png".

Czy ktoś może wskazać mi właściwy kierunek, co robię źle?

W rzeczywistości, łatki, których używam, są stosunkowo złożone i potrzebują trochę czasu, aby je wygenerować. Wolałbym nie modyfikować ich w razie potrzeby.

+1

Naprawdę dziwaczną częścią jest to, że dzieje się tak tylko wtedy, gdy wywołasz 'savefig', a nie jeśli wywołasz' show' ... –

Odpowiedz

2

Problemu można uniknąć, używając tych samych osi dla każdego wykresu, z ax.cla() wywołanym, aby wyczyścić wykres po każdej iteracji.

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

Dziękuję @unutbu! Działa świetnie. –

+0

Świetne; cieszę się, że mogłem pomóc! Proszę nie akceptować tej odpowiedzi, ponieważ chciałbym wiedzieć, dlaczego łata została przekształcona również w oryginalny kod. – unutbu

2

Alternatywą do odpowiedzi unutbu, znajduje się w użyciu pakiet copy, który można skopiować obiekty. Bardzo trudno jest zobaczyć, jak się zmieniają rzeczy po zadzwonieniu add_patch, ale tak właśnie jest. Zmieniają się właściwości łaty axes, ,. Niestety powierzchowne drukowanie każdej z tych właściwości skutkuje tym samym ciągiem znaków, więc wygląda na to, że się nie zmieniają. Ale podstawowe atrybuty niektórych lub wszystkich tych właściwości, np. extents, to Bbox, prawdopodobnie zostały zmienione.

Wywołanie kopiowania pozwoli ci uzyskać unikatową poprawkę do każdej postaci, bez znajomości rodzaju łatki. To nadal nie jest odpowiedź, dlaczego tak się dzieje, ale jak napisałem powyżej to alternatywne rozwiązanie problemu:

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

Również można użyć fig.savefig(str(count) + '.png'). To jawnie zapisuje figurę fig, gdzie jako plt.savefig zapisuje aktualną figurę, która jest właśnie tą, którą chcesz.