Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
182 views
in Technique[技术] by (71.8m points)

python - How can I attach a pyplot function to a figure instance?

Previously, I had a problem with the interference between multiple Matplotlib figures. Finally i got tracked that to an issue that some pyplot functions do not attach to their figure instance but can be rendered in some other figure instances which are created in parallel.

Here is some example code:

from django.http import HttpResponse
from numpy import arange, meshgrid
from matplotlib.mlab import bivariate_normal

def show_chart(request):
    delta = 0.025
    x = arange(-3.0, 3.0, delta)
    y = arange(-2.0, 2.0, delta)
    X, Y = meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)

    from matplotlib.pyplot import figure, contour
    fig1 = figure(figsize=(4, 4), facecolor='white')
    contour(X, Y, Z)

    response = HttpResponse(content_type='image/png')
    fig1.savefig(response, format='png')
    fig1.clear()
    return response

The contour pyplot function in the example above can get rendered in fig1, but occasionally also in some other figure that is generated in parallel. That is very annoying. Is there any way to attach the contour pyplot function to fig1?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As a bit of explanation of what is going on here, matplotlib has two semi-independent interfaces; the state machine and the OO interface.

The state machine code is designed for working in an interactive shell (and mimics matlab's interface). It does this by wrapping the OO interface in a set of commands that keep track of what the current figure and axes are. When you use the command from matplotlib.pyplot (I suspect you have an from matploblib.pyplot import * in your code) in is more or less equivalent to doing gcf().gca().contour(...). When you create a new figure, it is automatically made current (which is what you want if you are using this in an iteractive shell) so the behavior you see is the 'correct' behavior. The state machine interface also has code in it to make sure figures get re-drawn when they need to, manage the gui event loops, etc (all the things you need to do to make the interactive interface work smoothly). As hayden mentioned in comments, running ipython --pylab will automatically run from matplotlib.pyplot import *, which gives you a very nice interactive shell.

The OO interface is designed for programmatic dealing with matplotlib. What it adds in verbosity (you now have to do most of the work of the state machine), it makes up for in clarity. In the OO model, most (maybe all) of the plotting functions are associated with Axes objects (doc) (as there can be more than one axes associated with a figure (ex subplots using gridspec).

An alternate way to solve your problem is

ax = fig1.gca()

which will grab the current axes from fig1, creating one if necessary. This may be helpful if you keep track of your figure objects, but not your axes objects and want to add another graph to the figure.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...