Matplotlib

Notes on installing and using.

Matplotlib is cool. Did I say it was cool? I meant very cool. While principally a plotting library, it can be used for image manipulation and drawing.

draw_lines

Which is where our first problem occurs (as of the 0.8.4 version of matplotlib and possibly earlier). Should you try and use the Agg backend to draw a few lines on a picture like so:

from matplotlib.backends.backend_agg import RendererAgg
from matplotlib.transforms import Value

dpi = Value (72.0)
theIm = RendererAgg (400, 400, dpi)
theGc = theIm.new_gc()
theIm.draw_lines (theGc, (50 , 100 ), (150 , 200))

matplotlib will choke with the message:

IndexError: Unexpected SeqBase<T> length

draw_lines does more or less the same thing:

theIm.draw_lines (theGc, (10, 20, 30), (50, 60, 70))

The problem appears to be that draw_lines can be called with an optional argument to transform the line(s). If this is not passed, an assertion is triggered just at the start of RendererAgg::draw_lines within _backend_agg.cpp:

args.verify_length(4);

as there are only 3 arguments. draw_line runs into problems because it is implemented as a call to draw_lines. Although the transfrom argument is supposed to be set to None by default, this doesn't help because RendererAgg::draw_lines trys to access the ptr() argument of the transform. (In fact, it's worse as this has a tendency to kill the python interpreter.)

This problem can be solved from the user level by calling draw_lines with the identity transform (and where needed using draw_lines to draw a single line):

from matplotlib.transforms import identity_transform
identity_trans = identity_transform()
theIm.draw_lines (theGc, (50 , 100), (150 , 200), identity_trans)

This has been lodged as a bug. A followup to my report acknowledges the problem, saying it's the result of transition between old and new drawing APIs. In this light, my above solution seems reasonable.

More installation woes

In mid-2006, after getting a new MacBook, I spent three days trying to install matplotlib. It wasn't just one problem but a series of different issues that disguised each other. Thanks to the members of the matplotlib mailing list for helping me sort it out. (The technical parameters were, at the beginning: OSX 10.4, MPL 0.87.4, with numeric, numarray and numpy installed.)

The problems all surrounded the use of pylab. Matplotlib would install and import fine:

>>> import matplotlib

but when pylab was invoked, implicitly or explicitly, it would fail with a delightful variety of error messages. The first was:

>>> import pylab
[...] matrix undefined

The problem occured on line 74 of matplotlib/numerix/__init__.py where Matrix = matrix. matrix should have been defined when numpy was imported as the numerical library for MPL in the same file:

import numpy.oldnumeric as numpy
from numpy.oldnumeric import *

However, oldnumeric doesn't define a term matrix. Setting MPL to use Numeric instead of Numpy, this step is passed but I run into the next error, also at the import pylab stage:

Debug: ../src/common/object.cpp(224): assert
"sm_classTable->Get(m_className) == NULL" failed: class already in
RTTI table - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be
by linking some object module(s) twice)?
../src/common/object.cpp(224): assert
"sm_classTable->Get(m_className) == NULL" failed: class already in
RTTI table - have you used IMPLEMENT_DYNAMIC_CLASS() twice (may be
by linking some object module(s) twice)?

The first error is the result of an incompatibility between matplotlib 0.87.4 and numpy 1.0b and higher. The solution is to install matplotlib 0.87.5.

The second problem is caused by something entirely different. If you grep for sm_classTable in the MPL source, you'll find it in the wxagg sources. In fact, the problem turned out be with wxPython. MPL either couldn't find my wxPython installation or was finding the wrong. The environmental variable WX_CONFIG has to be set to the path of the wx-config executable for the correct installation. Once that is is done, MPL installs with fewer error messages (see below) and pylab imports and runs perfectly.

Another problem that occurred during this: MPL also requires freetype2, not freetype (1). Freetype seems to get installed by every second program and so there were multiple installations on my disk. In addition, freetype2 compilation is easy to screw up in the Mac / ppc / intel universe. If matplotlib / pylab finds the wrong or a bad freetype2 installation, you may get a lot of warnings or errors about legacy calls to _FontFamilyIterator etc. While it is probably possible to get the source compiled correctly using the right arguments to ./configure, in the end it proved easiest to get the library from Darwinports.

(As an aside, if you install Darwinports and then upgrade your home system Tcl/Tk, this may hose some Tcl packages required by port. See what a fun week I've had?)

As a further aside when matplotlib is built, a bunch of ominous but non-fatal warnings are generated like:

/usr/bin/ld: for architecture ppc /usr/bin/ld: warning fat file:
/usr/local/lib/libgcc_s.10.4.dylib does not contain an architecture
that matches the specified -arch flag: ppc (file ignored)

when linking various agg and _nc_transforms pieces, as well as:

src/_ns_backend_agg.cpp:41:1: warning: "M_PI" redefined
In file included from /usr/include/math.h:26, from
/Developer/SDKs/MacOSX10.4u.sdk/usr/include/c++/4.0.0/cmath

These appear to be spurious or at least don't interfere with the function of MPL.

Finally, it would do well to check what version of Xcode and DevTools you have. Despite having a brand new Mac, the version of XCode that came with it was significantly out of date, and may of had issues recognising the Intel architecture.