Reputation: 525
I haven't used Matplotlib much. Based on someone's advice, I'm trying to write some plotting codes using object-oriented paradigms as much as possible---and therefore trying to use pure Matplotlib (i.e. not relying on pyplot) to generate some simple figures.
A stripped-down version of my code looks like this:
import matplotlib as mpl
time = [0,1,2,3,4]
cell = [1,2,1,2,1]
sample = [3,2,3,4,4]
(figHt, figWd) = (5, 8) # in
lBorderWidth = bBorderWidth = rBorderWidth = tBorderWidth = 0.1
lbwh = (lBorderWidth, bBorderWidth,
(1-lBorderWidth-rBorderWidth),
(1-tBorderWidth-bBorderWidth)) # left, bottom, width, height
fig = mpl.figure.Figure(figsize=(figHt, figWd))
ax = fig.add_axes(lbwh)
lines1, = ax.plot(time,cell,'k--')
lines2, = ax.plot(time,sample,'k-')
fig.legend([lines1,lines2],['p','q'],'upper left')
fig.canvas.draw()
But when I run it, Python complains when it reaches fig.canvas.draw()
that canvas
type is None
.
Based on a reading of the Matplotlib Artists tutorial, it seems like pyplot
takes care of a few behind-the-scenes setup tasks, most notably establishing the connection between the Figure object and the desired renderer/backend. The tutorial says:
In the example below, we create a Figure instance using matplotlib.pyplot.figure(), which is a convenience method for instantiating Figure instances and connecting them with your user interface or drawing toolkit FigureCanvas. As we will discuss below, this is not necessary – you can work directly with PostScript, PDF Gtk+, or wxPython FigureCanvas instances, instantiate your Figures directly and connect them yourselves – but since we are focusing here on the Artist API we’ll let pyplot handle some of those details for us
Unfortunately, that particular page doesn't proceed beyond generating plots with pyplot.figure()
, so I am still trying to discover what the required steps are. Again, I realize pyplot can simplify this task---just trying to grok how all the pieces fit together.
I saw this description of a base class used by backends, FigureCanvasBase
, and I assume that I need to assign fig.canvas
one of FigureCanvasBase
's subclasses.
Also, I verified that Python is using a default backend. So I know the problem isn't caused by lack of a backend.
>>> matplotlib.backends.backend
'Qt4Agg'
Thanks in advance for any help. In summary, two questions:
FigureCanvasBase
to move forward. Even if the problem can probably be solved more elegantly, is there a way to search the Python environment for subclasses that inherit from FigureCanvasBase? This might come in handy in other problems. Upvotes: 2
Views: 2831
Reputation: 17475
You need to create a FigureCanvasAgg
in order to plot manually, try this:
import matplotlib as mpl
mpl.use('Agg') #setup the backend
import matplotlib.figure as mfigure
from matplotlib.backends.backend_agg import FigureCanvasAgg #canvas
time = [0,1,2,3,4]
cell = [1,2,1,2,1]
sample = [3,2,3,4,4]
(figHt, figWd) = (5, 8) # in
lBorderWidth = bBorderWidth = rBorderWidth = tBorderWidth = 0.1
lbwh = (lBorderWidth, bBorderWidth,
(1-lBorderWidth-rBorderWidth),
(1-tBorderWidth-bBorderWidth)) # left, bottom, width, height
fig = mfigure.Figure(figsize=(figHt, figWd))
canvas = FigureCanvasAgg(fig) #create the canvas
ax = fig.add_axes(lbwh)
lines1, = ax.plot(time,cell,'k--')
lines2, = ax.plot(time,sample,'k-')
fig.legend([lines1,lines2],['p','q'],'upper left')
fig.savefig('test.png') #save the figure
Note: You can find the subclasses of FigureCanvasBase
in matplotlib.backends.<your backend>.FigureCanvas<your backend>
Upvotes: 2