Matplotlib and Custom Fonts. A More Definitive Guide | by Ryan Louis Stevens | Towards Data Science

There’s two scenarios I’ve needed to use custom fonts. First, I’m on an OS with a limited number of pre-installed fonts (*cough* Microsoft *cough*). Second, I need to match the design aesthetic for a specific company I’m working for, or a project I’m working on.
To install a custom font to matplotlib requires two steps:
1. Installing custom font on your computer 2. Cleaning up and re-creating matplotlibs cache that stores font info
I will walk through both steps.
While there are plenty of resources online for using custom fonts in matplotlib, they suffer from two problems. First, they are sometimes not a complete guide, only showing you bits and pieces (such as how to re-load the matplotlib cache). Second, they abstract from interacting with fonts and their properties from within matplotlib. To understand fonts from within matplotlib, I will playing a lot with font_manager class, which has a lot of tools to improve both your font game, but also make writing reuseable code a lot simpler.
This walk through is focused on getting fonts to work, because of that I have provided links for how to install the fonts onto your computer.
We will be working with the “Proxima Nova” font.
Installing custom fonts on your computer is very easy. For Mac, you can use the “Font Books” app. For Windows, there is a similar workflow where you download a font and then drag and drop into an equivalent Windows’ fonts app.
For this exercise, I am on a Mac and have installed the “Proxima Nova” font. What does installing a font even mean? Well in our case, it means installing a .ttf (true type font) or .otf (original type font) file to a directory on the computer that Mac recognizes as the font directory. Specifically, one file it installed was this one :
ProximaNova-Regular.otf
This is an important point : fonts are just files on your computer.
All matplotlib does is assign a name, fname, in matplotlib to a file, name which is a location of a .ttf (or .otf) file on your computer.
To map font names to font files, matplotlib has a dictionary (or json file) located in its cache directory. Note, this file is not always in the same place, but usually sits at the home directory. If you are on mac (windows), it usually sits at whereever your HOME (%HOME%) environmental variable is set to.
To get matplotlib to recognize that we have a new font file on our computer, we just need to delete and reload this dictionary mapping font names to font files:
(1) Delete matplotlib font cache file (2) Re-create this file using matplotlib
For (1), you can remove the font list file from the command line. This is on Mac:
rm ~/.matplotlib/fontlist-v300.json
For (2), we are recreating that same json file we just deleted using the font_manager class from within python
from matplotlib import font_manager# Rebuild font cachefont_manager.__rebuild()
While this process tends to work, I have run into problems (especially on my other Windows machine). So before you run those two commands, let’s look at a few ways to verify what fonts matplotlib actually sees, i.e. those fonts available to be used from within matplotlib.
One way is to do a simple word search on the cache file fontlist-v300.json above. This file is in json format (basically a nested dictionary), each entry has a font and the fonts associated properties, such as the file associated with the font, fname, as well as, the associated weight (or thickness) of the font, weight.
One interesting thing is that you can see that font names repeat themselves. There are multiple entries that share the Helvetica font name attribute, but have different font files, which are shown in the fname attribute. Why is there a different font file for the same name? Because these are not the same exact font! The different font files are associated with different weight attributes (or how thick your characters are). There is separate files for the bold and normal font weight. Once again, fonts are just files.
I started this by saying you can inspect the cache file, so I went looking for name “Proxima Nova” in this file, and lo and behold it is not in the json cache file.
While the font cache file is nice, it would be a bit easier to inspect these within matplotlib. Luckily our font_manager class is able to do that. One way to inspect fonts is to get the list of FontEntry objects using our font_manager class. These are special objects that allow us to inspect fonts their properties. We see below we are accessing the ttflist attribute, which makes sense because “.ttf” files are the types of files fonts come from.
I showed above a rudimentary way to find all font names with Arial. However, matplotlib is already one step ahead of you. Within our font_manager class, there is a find_font function, which employs a nearest neighbor search method to try and a find a font with the name you give it. What we see if that it can’t find a Proxima Nova font file (as expected), and instead defaults to Deja Vu Sans.
After inspecting the files using the steps above, I returned to Step 2, deleted and re-created the cache. We can now check (from within python) that “Proxima Nova” can be found by our font_manager class. What we see now is that our “Proxima Nova” font can be found!
We can see that when we set the global rc param, that our font is now useable.
Another way of accomplishing similar goals is to set the font for specific objects on your plot. Here we change the global font to Comic Sans, and then change only the title of the plot to Proxima Nova. We use one of my favorite sub-classes of the font_manager class, the FontProperties classes. Here my variable myFont is a instance of this class, specifically, it’s a size 30, Proxima Nova font. The nice thing about this is you can create templates much easier if you simply create different FontProperties instances for different objects in your graph (such as title or axis label instance).
Getting custom fonts to work in matplotlib is a simple process, download the font files and then reload matplotlib caches. The main takeaway from this exercise is that fonts are files, and getting custom fonts to work is a process of getting matplotlib to find those files. To get deeper into all the methods and instances of the font_manager class, I suggest you checkout the font_manager class page from matplotlib developers. Happy plotting!