Reusing patch objects in matplotlib without them moving position

蹲街弑〆低调 提交于 2019-12-07 06:58:09

问题


I want to automatically generate a series of plots which are clipped to patches. If I try and reuse a patch object, it moves position across the canvas.

This script (based on an answer to a previous question by Yann) demonstrates what is happening.

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)

The first plot looks like this:

But in the second '1.png', the patch has moved..

However replotting again doesn't move the patch. '2.png' and '3.png' look exactly the same as '1.png'.

Could anyone point me in the right direction of what I'm doing wrong??

In reality, the patches I'm using are relatively complex and take some time to generate - I'd prefer to not have to remake them every frame if possible.


回答1:


The problem can be avoided by using the same axes for each plot, with ax.cla() called to clear the plot after each iteration.

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)



回答2:


An alternative to unutbu's answer, is to use the copy package, which can copy objects. It is very hard to see how things are changing after one calls add_patch, but they are. The axes, figure, extents,clip_box,transform and window_extent properties of the patch are changed. Unfortantely the superficial printing of each of these properties results in the same string, so it looks like they are not changing. But the underlying attributes of some or all of these properties, eg extents is a Bbox, are probably changed.

The copy call will allow you to get a unique patch for each figure you make, without know what kind of patch it is. This still does not answer why this happens, but as I wrote above it's an alternative solution to the problem:

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

Also you can use fig.savefig(str(count) + '.png'). This explicitly saves the figure fig where as the plt.savefig call saves the current figure, which happens to be the one you want.



来源:https://stackoverflow.com/questions/8166294/reusing-patch-objects-in-matplotlib-without-them-moving-position

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!