Installing matplotlib on OS-X (10.3.7)

Here are my notes on how to build matplotlib (0.81) installed and working on OS-X. I have so far kept a fink-free system, so that's what I've done here as well. I use it with the AGG back end for generating images for a web site, and hopefully with the wx backend for interactive use and embedding in wx Applications. I've also quickly got it working with TK.

Followiong these instructions shouls allow you to build a matplotlib for your system, as well as an installer for similar systems.

Note that this is kind of a running commentary, not well edited. I'd read the whole thing before starting.

1) Requirements:
-------------------------------------------
According to the matplotlib install docs (http://matplotlib.sourceforge.net/installing.html), you need the following:

zlib 
freetype (>= 2.1.7)
libpng

Personally, I've been avoiding Fink, as it doesn't seem to play well with the rest of OS-X, including the Apple supplied Python, so I've looked elsewhere for these libs.

a) zlib is installed by default on OS-X 

b) Freetype:

There is some version included with Apple's X11, but no one I know of has gotten it to work with matplotlib. I got a version from sourceforge:

http://freetype.sourceforge.net/index2.html

I got:

freetype-2.1.9.tar.gz

Following the instructions in docs/INSTALL.UNX:

$ ./configure --disable-shared --enable static 
$ make

I've built the static libs, so that matplotlib can link against them, and the resulting package can be put on a stock OS-X. While "--disable-shared" should have prevented teh shared libs (*.so or *.dylib) from being built, there were built in my case, I don't know why. You'll be putting the libs somewhere specific anyway, so it shouldn't matter. Don't install the shared ibs if you're trying to build it statically, they might get found and used instead of teh static ones.

If you are building matplotlib jsut for installation on the sytem you're building it on, you can just use:

$ ./configure
$ make
$ sudo make install

Which puts the shared lib in in /usr/local/..., which is a good place for it.

c) libpng:
I didn't have this on my system, except inside the wxWidgets source tree, so I went looking for it.

I did a google search for "libpng OS-X". I found:

http://www.libpng.org/pub/png/pngcode.html

Which led me to the libpng sourceforge site.

From there I downloaded: 

libpng-1.2.8.tar.gz

unpacked it, and opened a terminal in the libpng-1.2.8 directory, and did:

$ cp scripts/makefile.darwin ./makefile

This will make a copy of the MakeFile for OS-X, and put it where it needs to be. (note that according to the INSTALL, there is supposed to be a makefile.macosx, but it wasn't there)

I took a look in the makefile, and found:

ZLIBLIB=/usr/local/lib
ZLIBINC=/usr/local/include

Which is not where zlib is on my system. However, while I can find zlib.h, I couldn't fine the actual lib, so I tried make without changing anything.

$ make

Which seemed to work fine. zlib must be installed in a standard location, and gcc  found it.

You might want to do a:

sudo make install-static

That installs the static libs (*.a files) in /usr/local/lib, which is a pretty good place for them. You may not need to do this if you're only using libpng for matplotlib. See below.

If you want to do a dynamicl install, do:

$ sudo make install

to install the lib into /usr/local/ (this was specified in the makefile, and it's a good place for it)

Optional:
  $ make test
  and
  $ ./pngtest pngnow.png

  Which both seemed to pass. 

d) Numeric or numarray:

You'll need Numeric and/or numarray. Use whichever you prefer, or if you want to build something that others can use, install both, adn matplotlib will be build against both, and which one is used can be selected at runtime.

You can get them from:
http://www.pythonmac.org/packages/

Make sure to get them for the version of Python and OS-X that you have. Note that stuff built for OS-!0 10.3 wil work on 10.4, but maybe not the other way around.

e) The wanted back-ends:

Matplotlib can be used with Agg, for rendering PNG image files for web sites, etc, or be used interactively with wxPyton TkInter and PyGTK. PyGTK can only be used with X11, and therefore not really with the native Mac. I don't support that, so if you want that, go with and all-fink (or darwinports) system. If you want wxPython or TK, you need to install then first. wxPython can be installed with the installer on www.pythonmac.org/packages.

TK is a little trickier. There may be other ways to accomplish this, but this worked for me:

I downloaded the BI (Batteries Included) installer for tcl/Tk Aqua. It's got a lot of stuff I don't need, but it's only disk space. I then used the MacPython PackageManager and the standard package list, and installed Tkinter from there. It seemed to work.

With the 2.4.1 installer from undefined.org, you need to install tclTKAqua (if your runing OS-X 10.3), but Tkinter is part of the Python package.

3) Building matplotlib
First, you need to put the static libs you built somewhere that matplotlib will find them.

One option is to put them wherever "make install" puts them, but that can be a problem because if the linker finds both static and dydnamic libs, it will sue the dynamic ones. My solution is to created a directory in the matplotlib source tree (in the same place as setup.py) called "StaticLibs". That way I can assure that the linker will only find them.

In StaticLibs, there is:

drwxr-xr-x  4 cbarker  cbarker      136 15 Jun 11:18 include
-rw-r--r--  1 cbarker  cbarker  1800920  3 Feb 17:09 libfreetype.a
lrwxr-xr-x  1 cbarker  cbarker       10 13 Jun 11:57 libpng.a -> libpng12.a
-rw-r--r--  1 cbarker  cbarker   262992  3 Feb 17:09 libpng12.a

Note that libpng.a is alink to libpng12.a. The build process will look for "libpng.a". Note that these could be links to the libs installed in /usr/local or somewhere, if you want. 

The "include" directory has the freetype headers. It is a copy of the include directory from the libfreetype tarball.

I don't seem to need any libpng headers, which is odd. Perhaps I've got them installed somewhere standard on my system. If you have problems with compiling, I'd look into that as a possible issue.

I've set up matplotlibs setupext.py file to look for the StaticLibs directory. If it's there, it will add it, and nothing else, to the library search path, so it should use what you put there.

Here's what I've put in the top of setupext.py. Hopefully something like this will make it into the regular distribution.:

## CHB: added the following for some "smarts" on OS-X
import sys
if sys.platform == 'darwin': 
    ## This is OS-X is some form, but which?
    if os.path.isdir('StaticLibs'):
        # The StaticLibs dir is there, it should have everything needed.
        # that is: libfreeype.a and libpng.a
        darwinpath = ['StaticLibs']
    elif os.path.isdir('/sw'):
        # It looks like this is a fink system, so let's look there too:
        # Someone please check this: I don't have fink.
        darwinpath = ['/sw/lib/freetype219', '/usr/local', '/usr', '/sw', '/usr/X11R6']
    else:
        #Let's just try some generci locations
        # there should be a darwinports option here too, 
        # but I don't know what it wolud be.
        darwinpath = ['/usr/local', '/usr']
else:
    darwinpath = None
## Note: This is where you could put in whatever you want instead:
#darwinpath = ['/usr/local', '/usr', '/sw', '/usr/X11R6']


basedir = {
    'win32'  : ['win32_static',],
    'linux2' : ['/usr/local', '/usr',],
    'linux'  : ['/usr/local', '/usr',],
    'darwin' : darwinpath,
    'freebsd4' : ['/usr/local', '/usr'],
    'freebsd5' : ['/usr/local', '/usr'],
    'freebsd6' : ['/usr/local', '/usr'],    
    'sunos5' : [os.getenv('MPLIB_BASE') or '/usr/local',],
}



---------------------------------------------------------
By default, the matplotlib setup.py has "auto" for the back-end flags THis setting should built it for any back-ends that you have installed. For me, that means Agg and TK, and the wx back ends don't need any custom building. I do not hae PyGTK, so the GTKa nd GTKAgg back ends don't get built.

$python setup.py build

I get a bunch of warnings like:

ld: warning -L: directory name (StaticLibs/lib) does not exist

but it doesn't cause any problems.

If you have only the static version of libpng and libfreetype (*.a, and not *.dylib) in StaticLibs (or anywhere else on your lib search path), then it should link those statically. To test what it got linked against, you can do:

$ otool -L *.so

in the matplotlib directory that is buried in the build directory. it will tell you what libs the matplotlib extensions are linked to. They should not be linked to libfreetype or libpng. libz is OK, it's included with the stock OS-X.


4) Installing matplotlib:

To install it you have two options:

a) $ sudo python setup.py install

NOTE: in both these cases, the above will use whatever the default python is on your PATH. If you havn't installed a Python yourself, that will be the Apple-supplied Python. If you have, it may be Apple's and it may be yours, depending on whther you've messed with your PATH. What I do is use:

python2.4 setup.py .....

When I want to make sure to get version 2.4. I only recommend "Framework Build" Pythons for OS-X, rather than anything you get from fink, etc. If you want to use fink, use it for everything, including installing matplotlib. The "best" Python for OS-X today is 2.4.1, available from:

http://undefined.org/python/

b) Using Py2App (which you can get from: pythonmac.org/packages) to build an mpkg, then installing the resulting package. 

After installing py2app, you should have a tool in /usr/local/bin called "bdist_mpkg" that will Just Do It without any setup.py modifications to the target lib

In the matplotlib directory (the same place as setup.py)

$ bdist_mpkg

and it worked! "usr/local/bin" needs to be on your PATH. If it's not, add it, or just type the whole path to bdist_mpkg

Note: there are occasionally troubles with installing a newer matplotlib over an older one. You may want to remove an older version before installing, if you have one. To do this, delete:

/Library/Python/2.3/matplotlib/

With Python 2.4 there is an incompatibility between matplotlib and Py2App. The problem is that the matplotlib setup.py defines the data directory as:

share/matplotlib

but Py2App (and bdist_mpkg) add a share and you get:

/usr/local/share/share/matplolib

Until this issue is resolved, the work around is to hand-edit the Package. 

1) Right(or control) click on the mpkg, and select "Show Package contents"

2) Inside Contents.Packages, there are two packages. Inside the data package, in the contents folder, there is an info.plist.

3) double click on info.plist, and it will open in the plist editor

4) open up "root", and edit: IFPkgFlagDefaultLocation, removing the extra "share".Save it, close everything, and you should have a package that works.

(This is NOT required for python2.3)

Then click the mpkg. to install.

5) Editing matplotlibrc.

matplotlibrc is the preferecnce file for matplotlib. As it comes with matplotlib, the defaults expect PyGTK:

$python

>>> import pylab
Could not open font file /Library/Fonts/NISC18030.ttf
No module named pygtk
PyGTK version 1.99.16 or greater is required to run the GTK Matplotlib backends

This turns out to be because the matlabrc file sets the GTKAgg back end as the default. You have two choices. 

a) you can set the back end before importing pylab.
>>> import matplotlib
>>> matplotlib.use('Agg')
>>> import pylab

This works fine

b) Edit the matplotlibrc file. I found it in:
/System/Library/Frameworks/Python.framework/Versions/2.3/share/matplotlib/.matplotlibrc

Change the line:
backend      : GTKAgg    # the default backend
to
backend      : Agg    # the default backend

You can set it to TK or Wx if you want also. And you're all set to make images for the web, etc.

