What's the name of this font used in this figure? - python

I want to use this font in matplotlib plotting, but I can not find out the name. Does anyone know?
This figure is got by IDL plotting on Mac OS (10.9) like:
filename = 'name.eps'
myDevice = !D.NAME
SET_PLOT,'ps'
DEVICE,DECOMPOSED=1,ENCAPSULATED=1,/COLOR,FILENAME=filename
......
DEVICE, /CLOSE
SET_PLOT, myDevice

I'm not a font expert, but this looks a lot to me like the font that was used with pen plotters. Looking around for "pen plotter font", turns up "Hershey Vector Font", which looks quite close.

The font is indeed a Hershey vector font: Hershey Simplex Light. This user on Github has the font definition files (otf) that you can copy/clone into your system and set as the default fonts in your matplotlibrc. Not all the characters are included, but you can use fontforge to open the otf and/or sfd files and merge/copy/create missing glyphs.

(updated in 2022)
I think this font is a kind of vector font belonging to the Hershey family.
Here is a set of TTF fonts that are based on the Hershey font https://github.com/yangcht/Hershey_font_TTF.
You can download them and load them when you make plots.

Related

matplotlib + latex + custom ttf font

I have to make a figure in python. I need it to use the font Palatino. I downloaded the font here. I placed it under *\matplotlib\mpl-data\fonts\ttf (which turned out to be useless since I had to provide full path to make it work).
Using the following lines allows me to use the font:
prop = fm.FontProperties(fname='C:/Users/MyPC/pyApp/venv/Lib/site-packages/matplotlib/mpl-data/fonts/ttf/Palatino-Roman.ttf')
mpl.rcParams['font.family'] = prop.get_name()
Yay.
Now when I want to use Latex in matplotlib,
rc('text',usetex=True)
the font is now not the one I want. I tried to follow the official page about that and instead use:
rc('font',**{'family':'serif','serif':['Palatino']})
rc('text', usetex=True)
but I cannot see any difference. I tried all possibilities and it looks like the same font.
What am I doing wrong? Perhaps its the latex side that's lacking the required font package...
You can load any latex packages when using rc('text',usetex=True)
You can add this in your code:
plt.rcParams['text.latex.preamble'] = [r'\usepackage{palatino, mathpazo}']

Use matplotlib.pyplot.rcparams with a custom font which is not installed

I'm trying to use a custom ttf font not installed in the system for text element in the matplotlib figure.
with plt.style.context('mplparams.mplstyle'):
plt.plot(np.sin(np.linspace(0, 3 * np.pi)), '-o')
I know I can change the text properties with FontManager but I'm looking for a solution which only involves an external config file.
At the moment I only know that i can change font.sans-serif to a font name, not font path.
Is this possible?
The font to be used has to be known to the Fontmanager, otherwise you cannot get it into the plot. In order to specify a font through rcParams this font must be found in a folder matplotlib would look for it. In case you don't want to install anything, you may copy the .ttf file to the matplotlib font folder. In my case this is
python\Lib\site-packages\matplotlib\mpl-data\fonts
Then you need to clear the font.chache. Find out its path via print(matplotlib.get_cachedir()) and delete the fontList files. (Or make a backup first if you like).
Then run your script which has the rcParam specified
font.sans-serif : <name of font>
or use
plt.rcParams['font.sans-serif'] = "<name of font>"
Also see this question.

Get font file from font family

Having a difficult time trying to get the proper .ttf file from the font family.
Currently trying to use pygame to work on some graphics and it has its own internal search function to find a font file from the Font Family but it's not correct.
Also tried using matplotlib.font_manager. This also is not correct.
import matplotlib.font_manager as font_manager
import pygame
pygame.font.init()
print(font_manager.findfont('Segoe UI'))
> C:\WINDOWS\Fonts\seguisb.ttf
print(pygame.font.match_font('Segoe UI'))
> C:\WINDOWS\Fonts\segoeuil.ttf
print(font_manager.findfont('Arial'))
> C:\WINDOWS\Fonts\arial.ttf
print(pygame.font.match_font('Arial'))
> C:\WINDOWS\Fonts\ARIALN.TTF
I'm hoping there's something I missed and there is a way to get a complete match on the search, not a partial match (I'm guessing both methods used are reading the byte array and returning the closest matching font based on the Family. I.e., 'Segoe UI' is in 'Segoe UI Bold' so it was returned as the match).
I recommend to use pygame.font.SysFont():
Return a new Font object that is loaded from the system fonts. The font will match the requested bold and italic flags. Pygame uses a small set of common font aliases. If the specific font you ask for is not available, a reasonable alternative may be used. If a suitable system font is not found this will fall back on loading the default pygame font.

Creating a lightweight fallback font with fontforge and fonttools

For a webapp I need a way to prevent that a browser falls back to another font if my web font doesn't include a character. It seems the only way to do this is to add another font to the fontstack which includes "all" possible characters 1.
There are already existing fallback fonts, but those are more debug helpers as they show the codepoint as number, therefore they are much to heavy (>2MB).
The fallback font for my usecase should just show something like a box to signal a missing character.
My idea was to generate a simple font with only one glyph and apply a feature file which will replace all glyphs with this one.
My script for fontforge:
import fontforge
import fontTools.feaLib.builder as feaLibBuilder
from fontTools.ttLib import TTFont
font_name = 'maeh.ttf'
font = fontforge.font()
glyph = font.createChar(33, "theone")
pen = glyph.glyphPen()
pen.moveTo((100,100))
pen.lineTo((100,500))
pen.lineTo((500,500))
pen.lineTo((500,100))
pen.closePath()
for i in range(34, 99):
glyph = font.createChar(i)
glyph.width=10
font.cidConvertTo('Adobe', 'Identity', 0) # doesn't make a difference
font.generate(font_name)
font = TTFont(font_name)
feaLibBuilder.addOpenTypeFeatures(font, 'fallback.fea')
font.save("fea_"+font_name)
My feature file:
languagesystem DFLT dflt;
#all=[\00035-\00039];
##all=[A-Z] this works
feature liga {
sub #all by theone;
} liga;
But the above results in a
KeyError: ('cid00037', 'SingleSubst[0]', 'Lookup[0]', 'LookupList')
with changing numbers for cid00037.
If I use the out commented A-Z from the Feature file it works, so this approach doesn't seem to be completely wrong.
Why can't fonttools find the glyphs if I specify the range in CID notation?
Is there another way to crate a class for the OpenType feature file which includes all glyphs?
While working on the above problem, somebody hinted me to the Adobe NotDef font, which is pretty much what I was looking for. For some reason I wasn't able to convert the .otf of the Adobe NotDef to woff or woff2 with fontforge. Also all the online tools to create the web font files like fontsquirrel failed. To create the woff file I used sfnt2woff from the woff-tools package. For the woff2 file I used https://github.com/google/woff2.

Matplotlib PDF export uses wrong font

I want to generate high-quality diagrams for a presentation. I’m using Python’s matplotlib to generate the graphics. Unfortunately, the PDF export seems to ignore my font settings.
I tried setting the font both by passing a FontProperties object to the text drawing functions and by setting the option globally. For the record, here is a MWE to reproduce the problem:
import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm
data = scipy.arange(5)
for font in ['Helvetica', 'Gill Sans']:
fig = pylab.figure()
ax = fig.add_subplot(111)
ax.bar(data, data)
ax.set_xticks(data)
ax.set_xticklabels(data, fontproperties = fm.FontProperties(family = font))
pylab.savefig('foo-%s.pdf' % font)
In both cases, the produced output is identical and uses Helvetica (and yes, I do have both fonts installed).
Just to be sure, the following doesn’t help either:
matplotlib.rc('font', family = 'Gill Sans')
Finally, if I replace the backend, instead using the native viewer:
matplotlib.use('MacOSX')
I do get the correct font displayed – but only in the viewer GUI. The PDF output is once again wrong.
To be sure – I can set other fonts – but only other classes of font families: I can set serif fonts or fantasy or monospace. But all sans-serif fonts seem to default to Helvetica.
Basically, #Jouni’s is the right answer but since I still had some trouble getting it to work, here’s my final solution:
#!/usr/bin/env python2.6
import scipy
import matplotlib
matplotlib.use('cairo')
import matplotlib.pylab as pylab
import matplotlib.font_manager as fm
font = fm.FontProperties(
family = 'Gill Sans', fname = '/Library/Fonts/GillSans.ttc')
data = scipy.arange(5)
fig = pylab.figure()
ax = fig.add_subplot(111)
ax.bar(data, data)
ax.set_yticklabels(ax.get_yticks(), fontproperties = font)
ax.set_xticklabels(ax.get_xticks(), fontproperties = font)
pylab.savefig('foo.pdf')
Notice that the font has to be set explicitly using the fontproperties key. Apparently, there’s no rc setting for the fname property (at least I didn’t find it).
Giving a family key in the instantiation of font isn’t strictly necessary here, it will be ignored by the PDF backend.
This code works with the cairo backend only. Using MacOSX won’t work.
The "family" argument and the corresponding rc parameter are not meant to specify the name of the font can actually be used this way. There's an (arguably baroque) CSS-like font selection system that helps the same script work on different computers, selecting the closest font available. The usually recommended way to use e.g. Gill Sans is to add it to the front of the value of the rc parameter font.sans-serif (see sample rc file), and then set font.family to sans-serif.
This can be annoying if the font manager decides for some obscure reason that Gill Sans is not the closest match to your specification. A way to bypass the font selection logic is to use FontProperties(fname='/path/to/font.ttf') (docstring).
In your case, I suspect that the MacOSX backend uses fonts via the operating system's mechanisms and so automatically supports all kinds of fonts, but the pdf backend has its own font support code that doesn't support your version of Gill Sans.
This is an addition to the answers above if you came here for a non-cairo backend.
The pdf-backend of matplotlib does not yet support true type font collections (saved as .ttc files). See this issue.
The currently suggested workaround is to extract the font-of-interest from a .ttc file and save it as a .ttf file. And then use that font in the way described by Konrad Rudolph.
You can use the python-package fonttools to achieve this:
font = TTFont("/System/Library/Fonts/Helvetica.ttc", fontNumber=0)
font.save("Helvetica-regular.ttf")
As far as I can see, it is not possible to make this setting "global" by passing the path to this new .ttf file to the rc. If you are really desperate, you could try to extract all fonts from a .ttc into separate .ttf files, uninstall the .ttc and install the ttfs separately. To have the extracted font side-by-side with the original font from the .ttc, you need to change the font name with tools like FontForge. I haven't tested this, though.
Check if you are rendering the text with LaTeX, i.e., if text.usetex is set to True. Because LaTeX rendering only supports a few fonts, it largely ignores/overwrites your other fonts settings. This might be the cause.

Categories

Resources