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?
How to have a function return a figure in Python (using Matplotlib)? Set the figure size and adjust the padding between and around the subplots. Create x and y data points using numpy. Make a function plot(x, y) that creates a new figure or activate an existing figure using figure() method.
The plot() function of the pyplot module is used to create a figure.
The clf() function in pyplot module of matplotlib library is used to clear the current figure.
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.
You can create a subplot and than call the contour
method of the subplot:
fig1 = figure(figsize=(4, 4), facecolor='white')
ax = fig1.add_subplot(111)
ax.contour(X, Y, Z)
plt.subplots
makes it convenient to create a figure and subplots with a single call:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With