matplotlib show works while savefig fails for unicode - python

The following code produces the correct plot with plt.show() but fails when saved into a pdf or png image.
I have tried various suggestions (see commented lines) in similar questions, but none of them works for this case. Png file shows the unicode characters as boxes while pdf simply ignores them.
##-*- coding: utf-8 -*-
#from matplotlib import rc
#rc('font', **font)
#rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
#rc('font',**{'family':'serif','serif':['Palatino']})
#rc('text', usetex=True)
import matplotlib.pyplot as plt
plt.figure()
plt.plot(range(10))
plt.xlabel(u"\u2736")
plt.ylabel(u'\u03c4')
plt.savefig('unicode.pdf')
plt.savefig('unicode.png')
#plt.show()

You were nearly there when you tried changing the font family.
Only certain fonts support unicode characters. You can check which fonts you have installed via:
import matplotlib.font_manager as fm
set([f.name for f in fm.fontManager.ttflist])
Then change to a unicode font, e.g. DejaVu Sans in Linux, Arial Unicode MS for Windows, Lucida Grande for Mac OS X, more on Wiki. No need to use tex:
plt.rcParams['font.family'] = 'DejaVu Sans'

Related

I'm trying to use a Korean font on Matplotlib, but it is not working

The Korean font I am trying to link is not being applied--the graph is blank where Korean hangul would be.
I tried to link directly to a Korean font so as not to have to provide a local path, but it is still not working. It gives me errors saying the current font does not have that unicode character.
Here's the start of my code where I linked the font.
import re
import matplotlib.pyplot as plt
import lyricsgenius as genius
from matplotlib import font_manager
font_url = "https://fonts.googleapis.com/earlyaccess/nanumgothic.css"
font_prop = font_manager.FontProperties(fname=font_url)

matplotlib pgf pdfcomment preamble causing blank extra page

I am trying to add some tooltips to a matplotlib pdf file. To do this I am using pgf so I can add "pdfcomment" in the preamble. However, when I add pdfcomment to the preamble I get a blank extra page. This does not happen with other packages like xcolor and hyperref (for example).
Here is the code as I'm using it for testing, which I got from this discussion:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use("pgf")
pgf_with_pdflatex = {
"pgf.texsystem": "pdflatex",
"pgf.preamble": r"\usepackage{pdfcomment}",
}
mpl.rcParams.update(pgf_with_pdflatex)
fig = plt.figure(figsize=(4.5,2.5))
for i in range(5):
plt.text(i,i,r"\pdftooltip{\rule{0.3cm}{0.3cm}}{(%d,%d)}" % (i,i))
plt.plot(range(5), linewidth = 10)
plt.savefig("tooltips.pdf")
plt.close()
Which works, except that it makes an extra page. Below is a minimalist version which reproduces the problem.
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use("pgf")
mpl.rcParams["pgf.texsystem"] = "pdflatex"
#mpl.rcParams["pgf.preamble"] = r"\usepackage{pdfcomment}" # uncomment to get blank page
plt.plot(range(5), linewidth = 10)
plt.savefig("tooltips.pdf")
plt.close()
Essentially if you uncomment that one line you will get an extra blank page as output which I don't want. Below are two example screenshots that I get, one with the extra page and one without (all I changed was uncommenting the line).
As extra information, my pdflatex version is:
pdfTeX 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian)
python3 version is:
Python 3.8.10
Matplotlib version is:
3.3.2
Please help and please be kind, this is my first time posting a question.
Edit: as requested here is the intermediate LaTeX file. This is in the form of a pgf file which one would include in a tex document I think. I wasn't sure how to get the .tex directly.
It isn't pretty, but I think I found a work around. Here is the modified minimal version which only outputs a single page. Based on the comment by samcarter_is_at_topanswers.xyz, the problem is with matplotlib not LaTeX, so I just include a pdflatex call in the script. Here is the minimal working version:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use("pgf")
mpl.rcParams["pgf.texsystem"] = "pdflatex"
mpl.rcParams["pgf.preamble"] = r"\usepackage{pdfcomment}"
plt.plot(range(5), linewidth = 10, zorder = 10)
plt.savefig("tooltips.pgf")
plt.close()
import subprocess
with open("tooltips.tex", "w") as f:
f.write(r"""
\documentclass{standalone}
\usepackage{pgf}
\usepackage{pdfcomment}
\begin{document}
\input{tooltips.pgf}
\end{document}
""")
subprocess.run(["pdflatex", "tooltips.tex"])
Note that matplotlib outputs a .pgf file instead of a .pdf file.

Matplotlib annotate change font

I am trying to change the font type (from deja-vu to lets' say comic sans or calibri) for the text that appears along with matplotlib's annotate function. However, though I can change the font for all the other elements in the plot, it won't change it for the annotated text. Any help? Below is what I'm working with and how I globally set the font. You'll notice the difference in fonts when comparing the style of "1" on the plots.
import numpy as np
import os, glob
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager
from matplotlib import rcParams
import pdb
matplotlib.font_manager._rebuild()
# THIS SETS ALL THE RELEVANT FONT STYLE FOR PLOTS
rcParams['font.family'] = 'sans-serif'
rcParams['font.weight'] = 'regular' #can omit this, it's the default
rcParams['font.sans-serif'] = ['calibri']
# test code
ax = plt.figure().add_subplot()
x,y = np.arange(10),np.arange(10)
ax.plot(x,y)
ax.annotate(r'$100^\circ$',
xy=(1.1, 0.1), xycoords='axes fraction',
xytext=(1.1, 0.8), textcoords='axes fraction',
arrowprops=dict(facecolor='black', shrink=0.01),
horizontalalignment='center', verticalalignment='top',
fontsize=15)
The problem is, it's a mathematical text... if you change regular text's font characteristics, you're not going to affect the fonts that Matplotlib uses for mathematical text.
Of course you can modify the font used in mathematical text (is there anything in Matplotlib that you cannot modify?)
Writing mathematical expressions
[...] Mathtext can use DejaVu Sans (default), DejaVu Serif, the Computer Modern fonts (from (La)TeX), STIX fonts (with are designed to blend well with Times), or a Unicode font that you provide. The mathtext font can be selected with the customization variable mathtext.fontset (see Customizing Matplotlib with style sheets and rcParams).

Getting semi-transparent text with matplotlib+pgf backend when compiling in LateX

So I am using the pgf backendin matplotlib to include some automatically compiled references to some other parts of my Tex documents (figures, bibliography) in my TeX document.
import matplotlib
matplotlib.use('pgf')
import matplotlib.pyplot as plt
plt.figure()
plt.txt(0.0,0.5,r'Some text compiled in latex \cite{my_bib_tag}')
plt.savefig("myfig.pgf", bbox_inches="tight", pad_inches=0)
Then in my tex document I have the lines:
\usepackage[dvipsnames]{xcolor}
%yada yada yada
\begin{figure}
\input{myfig.pgf}
\end{figure}
It is working great but when I try to add some transparency to the text it doesn't work. For instance when setting:
plt.txt(0.0,0.5,r'Some text compiled in latex \cite{my_bib_tag}', alpha=0.5)
The text appears unchanged, and if I try to do it in the compilation by using \textcolorfrom the xcolor package (or any other commands in LateX, like the transparent package) I get parsing errors when compiling the Python.
I tried escaping characters but somehow I cannot make it work.
plt.txt(0.0,0.5,r'\textcolor{gray}{Some text compiled in latex \cite{my_bib_tag}}', alpha=0.5)
#raise ValueError !Undefined Control Sequence
EDIT 1: I tried adding the required package in the preamble, but it does not work when saving to pgf (with the pgf backend), it works using the Agg backend (I think it is expected behavior). But I need to save it in pgf to have the dynamic parsing of references.
import matplotlib
import matplotlib.pyplot as plt
matplotlib.rcParams["text.usetex"] = True
matplotlib.rcParams["text.latex.preamble"].append(r'\usepackage[dvipsnames]{xcolor}')
matplotlib.verbose.level = 'debug-annoying'
plt.figure()
plt.text(0.0,0.5,r'\textcolor{gray}{Some text compiled in latex \cite{my_bib_tag}}', alpha=0.5)
#works in .png, does not work in .pgf
#plt.savefig("myfig.png", bbox_inches="tight", pad_inches=0)
EDIT 2: A work around is to use the color param in plt.text but what if I would like to use more complicated LateX styling...
Thanks to #ImportanceOfBeingErnest I finally made it work with the pgf backend:
import matplotlib
matplotlib.use('pgf')
import matplotlib.pyplot as plt
pgf_with_custom_preamble = {
"text.usetex": True, # use inline math for ticks
"pgf.rcfonts": False, # don't setup fonts from rc parameters
"pgf.preamble": [
"\\usepackage[dvipsnames]{xcolor}", # load additional packages
]
}
matplotlib.rcParams.update(pgf_with_custom_preamble)
plt.figure()
plt.text(0.0,0.5,r'\textcolor{gray}{Some text compiled in latex \cite{my_biblio_tag}}')
plt.savefig("myfig.pgf", bbox_inches="tight", pad_inches=0)

Writing Greek in matplotlib labels, titles

I am trying to write some text in Greek for labels, figure title etc. to accompany my plots but so far to no avail.
I don't want to print specific letters (I know how to do this using the special characters notation), I'd rather write the whole text in Greek (probably using Unicode and u'text' ?).
Before receiving suggestions I would like to mention that for some reason I can't get matplotlib to cooperate with TeX (using Ipython notebook from anaconda in Ubuntu 14.10), so that wouldn't really be an option.
I tried loading Arial font and it does load successfully but again I get square blocks instead of characters. I used
import matplotlib.font_manager as fm
prop = fm.FontProperties(fname='/usr/share/fonts/truetype/msttcorefonts/Arial.ttf')
and then for displaying the string I used u'Αποτελέσματα προσομοίωσης'. Arial is supposed to render Greek perfectly and I have used it many times in text editors.
I managed to solve the problem by doing the following:
First, you have to import the necessary libraries and set a font installed on the computer that can for sure render Greek, like the Ubuntu font (Ubuntu Bold in the following code).
import matplotlib.font_manager as fm
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
then you can specifically apply the chosen font to each label, title etc as follows:
plt.title(u"Τίτλος του γραφήματος",fontproperties=fp1)
If that doesn't seem to work, try adding the following line at the beginning of the file:
# -*- coding: utf-8 -*-
A sample plot is provided to prove the correctness of the code:
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import numpy as np
fp1 = fm.FontProperties(fname='/usr/share/fonts/truetype/ubuntu-font-family/Ubuntu-B.ttf')
data = np.random.randn(5000) #generate some random data
plt.plot(data)
plt.title(u"Τίτλος του γραφήματος", fontproperties=fp1)
plt.xlabel(u"Άξονας x", fontproperties=fp1)
plt.ylabel(u"Άξονας y", fontproperties=fp1)
plt.show()
It should give you something like that:

Categories