Повторное использование объектов патча в matplotlib без их перемещения - PullRequest
5 голосов
/ 17 ноября 2011

Я хочу автоматически генерировать серию графиков, которые обрезаются на участки. Если я пытаюсь повторно использовать объект патча, он перемещается по холсту.

Этот сценарий (основанный на ответе на предыдущий вопрос Янна) демонстрирует, что происходит.

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)

Первый сюжет выглядит так: Correct position of patch - first time plotted

Но во втором '1.png' патч сместился .. Wrong position of the patch

Однако повторная печать не перемещает патч. «2.png» и «3.png» выглядят точно так же, как «1.png».

Может ли кто-нибудь указать мне правильное направление того, что я делаю неправильно?

На самом деле, патчи, которые я использую, являются относительно сложными и занимают некоторое время для генерации - я бы предпочел не переделывать их каждый кадр, если это возможно.

Ответы [ 2 ]

2 голосов
/ 17 ноября 2011

Альтернативой ответу unutbu является использование пакета copy, который может копировать объекты.Очень трудно увидеть, как все меняется после одного звонка add_patch, но это так.Свойства патча axes, figure, extents, clip_box, transform и window_extent изменены.К сожалению, поверхностная печать каждого из этих свойств приводит к одной и той же строке, поэтому похоже, что они не меняются.Но базовые атрибуты некоторых или всех этих свойств, например, extents - это Bbox, вероятно, изменены.

Вызов копирования позволит вам получить уникальный патч для каждой фигуры, которую вы делаете, не зная, что это за патч.Это все еще не отвечает, почему это происходит, но, как я уже писал выше, это альтернативное решение проблемы:

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

Также вы можете использовать fig.savefig(str(count) + '.png').Это явно сохраняет фигуру fig, где при вызове plt.savefig сохраняется текущая фигура, которая, как вам нужно.

2 голосов
/ 17 ноября 2011

Эту проблему можно избежать, используя одинаковые оси для каждого графика, при этом ax.cla() вызывается для очистки графика после каждой итерации.

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