Tuesday, June 18, 2013

Matplotlib (and SciPy) on OS X Mountain Lion

Yesterday I installed matplotlib on my MacBook---for about the 10th time. This can be a complex undertaking, but a basic installation is relatively easy, so I thought I would outline it here.

Some things I did that made it easier:

• I used a clean install of OS X. I did this to make sure cruft (links, alternative versions of libraries from old installs) does not interfere. Also, this way I can be sure that things work for the reasons I have written about here.

To do the install I just made a second partition on my hard drive and installed OS X on it from a USB installer. If you've never done this before, good instructions for the USB part are here.

It's quite straightforward. Use the App store to update when the install is complete. I now have OS X 10.8.4.

Although it's not necessarily good practice, I used the same username and password for my accounts on OS X on both partitions, this allows me to read and write files in both accounts easily using the Finder.

• I used the System Python. This doesn't appear to be a very popular choice, but it avoids the headache of having multiple Pythons and various $PATH issues, etc. If you do install a second Python, make sure it's a framework version, since even saving a plot as a png using matplotlib will fail otherwise. I may do some more experiments later, but I think this is the right choice

My Python is

$ which python
/usr/bin/python

(well, it's not really the whole of Python on OS X, but that is a whole 'nother story).

$ python
Python 2.7.2 (default, Oct 11 2012, 20:14:37)

A bonus is that we already have numpy

>>> import numpy
>>> numpy.__version__
'1.6.1'

• I used Homebrew to get the most important matplotlib prerequisites, libpng and freetype. zlib is also a prerequisite but comes with OS X.

The instructions for Homebrew are here. Weirdly, I got a prompt for an admin password, which happened because the directory where Homebrew puts stuff, /usr/local, did not exist yet. So I bailed from the process and first did:

sudo mkdir /usr/local

Now, look for issues revealed by brew doctor and fix them if needed. Finally:

$ brew doctor
Your system is ready to brew.
$ brew update
Already up-to-date.
$ brew install pkgconfig libpng freetype
..
$ brew list
freetype libpng  pkg-config

the "Bottles" mentioned in the output I cut means these are pre-built.

I got pkgconfig because it helped with building/linking problems previously, but should not really be necessary when the libraries are in /usr/local. Not sure why it is some times pkg-config and other times pkgconfig, but OK:

$ ls /usr/local/bin/pkg-config 
/usr/local/bin/pkg-config
$ ls /usr/local/lib/pkgconfig/
freetype2.pc libpng.pc libpng15.pc

(If you use e.g. the XQuartz versions of these two libraries, you can set the PKG_CONFIG_PATH environment variable to point to the correct directory, and pkg-config will do the rest).

Now we're ready for matplotlib.

$ git clone git://github.com/matplotlib/matplotlib.git
..
$ cd matplotlib
$ python setup.py build
$ sudo python setup.py install

And test it:

cd ..
python 
>>> import matplotlib.pyplot as plt
>>> Y = [1,4,9,16]
>>> plt.scatter(range(len(Y)),Y,s=250,color='r')
<matplotlib.collections.PathCollection object at 0x103963110>
>>> plt.savefig('example.png')

Works!

>>> import matplotlib
>>> matplotlib.test()
..KK.KK.....KK.KK..KK.KK.KK.KK.KK  etc.

I didn't test extensively but there don't seem to be massive failures. And matplotlib has lots of optional prerequisites I didn't install that would explain some failures.

It's worth pointing out that the matplotlib install process grabs several additional packages:

$ ls /Library/Python/2.7/site-packages
README
distribute-0.6.28-py2.7.egg
easy-install.pth
matplotlib-1.4.x-py2.7-macosx-10.8-intel.egg
nose-1.3.0-py2.7.egg
pyparsing-1.5.7-py2.7.egg
setuptools.pth
tornado-3.1-py2.7.egg
$

Let's get a few more things while we're at it:

$ sudo easy_install pip
Password: ****
Searching for pip
Reading http://pypi.python.org/simple/pip/
Best match: pip 1.3.1
..
Installing pip script to /usr/local/bin
Installing pip-2.7 script to /usr/local/bin
..

Come to think of it, SciPy would be a great addition. For that we need gfortran (Fortran compiler) and Cython:

$ brew install gfortran
(takes a while, several dependencies)..

Homebrew doesn't have Cython so:

$ sudo pip install cython

And now for SciPy:

$ git clone git://github.com/scipy/scipy.git scipy

$ cd scipy
$ python setup.py build
$ sudo python setup.py install

$ cd ..
$ python
..
>>> from scipy.stats import norm
>>> norm.cdf(2)
0.97724986805182079
If you check for the libraries loaded (I used export DYLD_PRINT_LIBRARIES=1), you'll see we're using Accelerate.

Finally, get PyCogent too..

$ git clone git://github.com/pycogent/pycogent.git
$ cd pycogent
$ python setup.py build
$ sudo python setup.py install

That was pretty easy!