Cyrillic and other non-ASCII characters in matplotlib
23.07.2009 17:49 · Notes · matplotlib, python, tips
There is a wonderful Python library — matplotlib. It is a plotting library that supports a wide range of plot types and is designed to emulate MATLAB commands and behaviour. The library is easy to learn; to draw a simple plot, you literally need two commands. I have used this library in my Statist plugin for QGIS and in another GIS project. To make installation of matplotlib more convenient for inexperienced users, I recently packaged it for OSGeo4W.
Sometimes, I needed to display non-ASCII (namely Cyrillic) characters on matplotlib plots. And there was a problem: such text was drawn as empty squares. Reading manuals, googling, and asking on the mailing list led to two solutions that I would like to share with you.
Method 1: the almighty TeX
matplotlib can use LaTeX to display both plain text and mathematical symbols. Moreover, a limited subset of TeX and the corresponding parser, fonts, and renderer are built into the library, so for this subset, you do not even need to have a full TeX installation. Unfortunately, this TeX subset only contains mathematical characters and letters of the Greek alphabet. In all other cases, an external LaTeX installation is required. To use LaTeX for text rendering, we should set the option
text.usetex: True
in the rc-file. This can be done either globally, by editing the rc-file once, or as needed at runtime. Below is an example of run-time initialisation:
# -*- coding: utf-8 -*-
from matplotlib import rc
rc("font", {"family": "serif"})
rc("text", usetex=True)
rc("text.latex", unicode=True)
rc("text.latex", preamble="usepackage[utf8]{inputenc}")
rc("text.latex", preamble="usepackage[russian]{babel}")
Now we can output Cyrillic (or any other non-ASCII characters)
xlabel(u"Вісь Х: довжина, см")
The big disadvantage of this method is that the user needs to have LaTeX installed.
Method 2: unicode + fonts
matplotlib uses its own font rendering engine with full Unicode support. Therefore, we can explicitly specify a font that contains the required character sets and render the text using that font. Here is a small example:
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
plt.rcParams["text.usetex"] = False
fp = fm.FontProperties(fname="/home/alex/.fonts/academy.ttf")
plt.text(0.5, 0.5, u"кириличний текст", fontproperties=fp)
plt.show()
There is also a disadvantage — the required font may not be available on the target system or may be in a different directory, so the font has to be stored in the same directory as your program. But in my opinion, this is much better than having LaTeX as a dependency.
Personally, I chose the latter option.