16

I am trying to change the matplotlib font to helvetica, which I'd like to use in a PDF plot. I try the following:

import matplotlib
matplotlib.use('PDF')
import matplotlib.pylab as plt
from matplotlib import rc
plt.rcParams['ps.useafm'] = True
rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
plt.rcParams['pdf.fonttype'] = 42

This does not work -- when I run my code with --verbose-debug, I get the error:

backend WXAgg version 2.8.10.1
/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/site-packages/matplotlib/__init__.py:833: UserWarning:  This call to matplotlib.use() has no effect
because the the backend has already been chosen;
matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
or matplotlib.backends is imported for the first time.
findfont: Could not match :family=sans-serif:style=normal:variant=normal:weight=normal:stretch=normal:size=medium. Returning /Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf
Assigning font /F1 = /Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf
Embedding font /Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/site-packages/matplotlib/mpl-data/fonts/ttf/Vera.ttf
Writing TrueType font

So apparently it cannot find Helvetica. I am not sure why. I have Helvetica in the afm directory of mpl-data, and when matplotlib initiates it reads it and outputs:

createFontDict: /Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/site-packages/matplotlib/mpl-data/fonts/afm/Helvetica.afm

Do I need a special .ttf Helvetica font in addition? If so, how can I get it? I know I have Helvetica on my system since I see it in Illustrator and many other programs.

I am using Enthought Python distribution as follows:

$ python
Enthought Python Distribution -- http://www.enthought.com
Version: 6.2-2 (32-bit)

Python 2.6.5 |EPD 6.2-2 (32-bit)| (r265:79063, May 28 2010, 15:13:03) 
[GCC 4.0.1 (Apple Inc. build 5488)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.__version__
'0.99.3'

Any ideas how this can be fixed?

thanks.

3 Answers3

20

Step-by-step solution for OS X 10.11 El Capitan and Python 3 (based on this post).

  1. Install fondu: brew install fondu
  2. Find out matplotlib location:

    python3 -c "import matplotlib ; print(matplotlib.matplotlib_fname())" 
    

    For me it's /usr/local/lib/python3.5/site-packages/matplotlib/mpl-data/matplotlibrc

  3. Make a copy of Helvetica:

    mkdir ~/Desktop/font_copies
    cp /System/Library/Fonts/Helvetica.dfont ~/Desktop/font_copies
    
  4. Convert the Helvetica copy we've made from dfont to ttf:

    cd /usr/local/lib/python3.5/site-packages/matplotlib/mpl-data/fonts/ttf/
    fondu -show ~/Desktop/font_copies/Helvetica.dfont
    
  5. Remove font cache: rm ~/.matplotlib/fontList.py3k.cache

Done! Now you can use Helvetica:

import matplotlib.pyplot as plt
plt.rc('font', family='Helvetica')
Max Malysh
  • 29,384
  • 19
  • 111
  • 115
  • 1
    This step-by-step solution works perfectly and should be up-voted! – meduz Apr 21 '16 at 10:54
  • 1
    This should be the accepted answer. Thanks so much! – Luke Davis Dec 08 '17 at 12:18
  • 2
    You may also need remove: ``~/.matplotlib/fontList.json`` and ``~/.matplotlib/fontList.cache``. – Libin Wen Jul 10 '19 at 07:19
  • On my Catalina machine the file is `Helvetica.ttc`, not `Helvetica.dfont`. I couldn't figure out how to use `fondu` for this, but there are online services which perform TTC -> TTF conversion which worked. As @LibinWen says you may also need to remove other font cache files. – orthocresol Dec 04 '20 at 11:01
18

The solution is to use fondu to convert the .dfont Helvetica font from Mac OS X into .ttf, and then place that in the mpl-data/fonts directory that Matplotlib looks in. That solved the issue.

  • 4
    Thanks for asking the question and answering it — I'm sure this will come in helpful to me sometime, and this is exactly the sort of thing StackOverflow was created for. – ShreevatsaR Jul 04 '10 at 22:18
  • Could you provide with more details? The step-by-step solution by Max Malysh works like a charm! – meduz Apr 21 '16 at 10:55
0

In case it helps anyone, I wrote a script that automatically adds .ttf fonts from a custom folder to mpl-data. Place your .ttf files in some folder, and run this script to move them.

#!/usr/bin/env python3
# Imports
import os
import re
import shutil
from glob import glob
from matplotlib import matplotlib_fname
from matplotlib import get_cachedir

# Copy files over
_dir_data = re.sub('/matplotlibrc$', '', matplotlib_fname())
dir_source = '<your-font-directory-here>'
dir_dest = f'{_dir_data}/fonts/ttf'
# print(f'Transfering .ttf and .otf files from {dir_source} to {dir_dest}.')
for file in glob(f'{dir_source}/*.[ot]tf'):
    if not os.path.exists(f'{dir_dest}/{os.path.basename(file)}'):
        print(f'Adding font "{os.path.basename(file)}".')
        shutil.copy(file, dir_dest)

# Delete cache
dir_cache = get_cachedir()
for file in glob(f'{dir_cache}/*.cache') + glob(f'{dir_cache}/font*'):
    if not os.path.isdir(file): # don't dump the tex.cache folder... because dunno why
        os.remove(file)
        print(f'Deleted font cache {file}.')

This originally appeared in this stackoverflow post.

Luke Davis
  • 2,548
  • 2
  • 21
  • 43