3

I downloaded fonts from Google Fonts which I want to use for my thesis and all plots, namely the Alegreya font family. After installing the fonts to $HOME/.fonts I removed .cache/matplotlib/fontList.cache and created a plot with the new font.family = 'Alegreya Sans' in the rcParams. Unfortunately, matplotlib detects the Thin font of Alegreya Sans as the Regular one. The false detection is illustrated by the following minimal example:

import matplotlib.font_manager

weights = ['ultralight', 'light', 'normal', 'regular', 'book', 'medium', 
           'roman', 'semibold', 'demibold', 'demi', 'bold', 'heavy', 
           'extra bold', 'black']

print 'weight'+6*' ', 'file name', '\n'+70*'-'
for weight in weights:
    fprops = matplotlib.font_manager.FontProperties(family='Alegreya Sans', 
                                                    weight=weight)
    print weight+(12-len(weight))*' ', matplotlib.font_manager.findfont(fprops)

Output:

weight       file name 
----------------------------------------------------------------------
ultralight   /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Light.ttf
light        /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Light.ttf
normal       /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Thin.ttf
regular      /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Thin.ttf
book         /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Thin.ttf
medium       /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Medium.ttf
roman        /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Medium.ttf
semibold     /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
demibold     /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
demi         /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
bold         /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
heavy        /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
extra bold   /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-ExtraBold.ttf
black        /hmi/kme/.fonts/Alegreya_Sans/AlegreyaSans-Black.ttf

How can this be fixed and why does it happen? Thanks in advance!

Edit:

Of course, there are more files in the folder /hmi/kme/.fonts/Alegreya_Sans/

A complete list:

  • AlegreyaSans-BlackItalic.ttf
  • AlegreyaSans-BoldItalic.ttf
  • AlegreyaSans-ExtraBoldItalic.ttf
  • AlegreyaSans-Italic.ttf
  • AlegreyaSans-Light.ttf
  • AlegreyaSans-Medium.ttf
  • AlegreyaSans-ThinItalic.ttf
  • AlegreyaSans-Black.ttf
  • AlegreyaSans-Bold.ttf
  • AlegreyaSans-ExtraBold.ttf
  • AlegreyaSans-LightItalic.ttf
  • AlegreyaSans-MediumItalic.ttf
  • AlegreyaSans-Regular.ttf
  • AlegreyaSans-Thin.ttf

My System

  • OpenSuse 13.1
  • python 2.7
  • matplotlib version 1.4.3
carlo_barth
  • 329
  • 4
  • 13
  • Using the same version of matplotlib and python, but on a mac (10.10.5), I get a different result. where you get `AlegreyaSans-Thin.ttf`, I get `AlegreyaSans-Regular.ttf`, and where you get `AlegreyaSans-ExtraBold.ttf`, I get `AlegreyaSans-Bold.ttf`. Everything else is the same. Not sure if that's any help, but though it at least adds a datapoint! – tmdavison Aug 19 '15 at 11:18
  • Huh, actually, that's weird. My result in the comment above was true if the fonts were directly in `$HOME/.fonts`. If I move them into a subdirectory `$HOME/.fonts/Alegreya_Sans`, as you have, I get the same result as you – tmdavison Aug 19 '15 at 11:22
  • @tom This sounds very strange. How can this be? I wonder what matplotlib is using to detect the font weight. Obviously they are not parsing the file name :) Sad that I do not understand the syntax in fontList.cache, so even a manual fix can't be done. Any further ideas? – carlo_barth Aug 19 '15 at 12:21
  • @tom I checked it now using all .ttf-files in .fonts without subdirectories. This is even more weird: I'm getting the same output as you now, i.e. Thin replaced by Regular and so on, but it still uses the Thin-font in the output pdf. Any help appreciated. – carlo_barth Aug 19 '15 at 12:30
  • did you clear the font cache again? Sorry, I don't know much about how font_manager works, but hopefully someone more knowledgable will be along soon :) – tmdavison Aug 19 '15 at 12:34
  • could also be a backend thing? try [here](http://stackoverflow.com/questions/12790284/why-doesnt-matplotlib-use-the-ttf-font-that-i-provide) – tmdavison Aug 19 '15 at 12:44
  • I’ve created a [bug report for this problem](https://github.com/matplotlib/matplotlib/issues/8550). – Rufflewind Apr 29 '17 at 23:04

2 Answers2

2

I fixed the problem manually with a work-around. Anyhow this seems to be a bug. As tom mentioned, I copied all fonts to $HOME/.fonts without subdirectories. This changed the output from the script I gave in the question. To find out what's wrong I tried to print all combinations of weight and style of Alegreya and Alegreya Sans in the following way:

import matplotlib
matplotlib.use('Qt4Agg')
print matplotlib.get_backend()
import matplotlib.pyplot as plt

alignment = {'horizontalalignment':'center', 'verticalalignment':'baseline'}
alegreya_weights = { 'Alegreya': ['regular', 'bold', 'black'],
                     'Alegreya Sans': ['ultralight', 'light', 'regular', 
                                       'medium', 'bold', 'extra bold', 
                                       'black'] }
styles = ['normal', 'italic']

combinations = []
for family in alegreya_weights.keys():
    for style in styles:
        for weight in alegreya_weights[family]:
            combinations.append((family, weight, style))
N = len(combinations)

def textPlot(ax, i, N, family, weight, style):
    y = 1.-(1./float(N)) -float(i)/(float(N)+1)
    ax.text(0.5, y, family+' '+weight+' '+style, 
            family=family, weight=weight, style = style, 
            fontsize = 30, **alignment)

fig = plt.figure(figsize=(8, .7*N), frameon=False)
ax = plt.gca()
ax.axis('off')
plt.xlim((0.,1.))
plt.ylim((0.,1.))

for i,c in enumerate(combinations):
    textPlot(ax, i, N, c[0], c[1], c[2])

plt.show()

It turned out that only AlegreyaSans-Regular.ttf was replaced by AlegreyaSans-Thin.ttf. I couldn't find out if this is due to the word "Thin", which is referred to as "ultralight" in matplotlib-syntax. I replaced "AlegreyaSans-Thin.ttf" by "AlegreyaSans-Regular.ttf" in $HOME/.cache/matplotlib/fontList.cache to solved the problem.

Now the following image results from the script above. Thin (ultralight) is not detected.

enter image description here

Thanks to tom for any help.

carlo_barth
  • 329
  • 4
  • 13
  • Matplotlib currently has an [open issue on this subject](https://github.com/matplotlib/matplotlib/issues/8788). When adding fonts to matplotlib you have to delete all of the "thin" files unfortunately! – Luke Davis Dec 18 '19 at 02:30
2

Thank you for posting this - I experienced similar issues with being unable to display the correct font weight while attempting to install the Fira Sans font to work with matplotlib. Your diagnostic for associating font weights to filenames was extremely helpful.

On Mac, I fixed my problem my removing all Fira Sans .ttf files on my computer and reinstalling ab initio via Font Book. It turned out that I had previously placed several Fira Sans font files (including FiraSans-Regular) in other font directories when I didn't know what I was doing. Subsequently, when I tried to use Font Book to install Fira Sans, the regular typeface failed to install properly, leading to weird font selection by fontmanager.

tl;dr - If you run the diagnostic above and don't see the filename you expect next to a given weight, check that the typeface is correctly installed in Font Book.

Magrathean
  • 21
  • 4