Writing Greek in matplotlib labels, titles - python

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:

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.

Customize font when using style sheet

I am using the 'ggplot' style sheet. Now, the style is great, except that I would like to specifically change the font style. Is that possible?
If found the documentation about customizing styles. However, I just want to change the font while keeping the rest of the style.
Also, does anyone know where to see the setting-details of each style (like font, figsize, etc.)?
plt.imshow(ori, vmin = 0, vmax = 300)
plt.style.use('ggplot')
plt.show()
Combining styles
I think that the most elegant is to combine styles.
For example, you could define your own font settings in mystyle.mplstyle (see below where to save it, and what it could look like). To get the ggplot style with your own font settings you would then only have to specify:
plt.style.use(['ggplot', 'mystyle'])
This solution is elegant, because it allows consistent application in all your plots and allows you to mix-and-match.
Where to save your custom style?
Taken from one of my own styles mystyle.mplstyle could have the following entries (you should customise to your need obviously):
font.family : serif
font.serif : CMU Serif
font.weight : bold
font.size : 18
text.usetex : true
Which you should save it matplotlib's configuration directory. For me this is ~/.matplotlib/stylelib/, but use
import matplotlib
matplotlib.get_configdir()
to find out what to use on your operating system. See documentation. You could also write a Python function to install in the right location.
Where to find existing styles?
Then the final part of your question. First, it is usefull to know that you can obtain a list with available styles using
import matplotlib.pyplot as plt
plt.style.available
See the documentation for a graphical representation.
How to inspect for example ggplot.mplstyle? I think that the best reference in matplotlib's source. You can also find the *.mplstyle files on your system. Where, however, depends on your operating system and installation. For me
find / -iname 'ggplot.mplstyle' 2>/dev/null
gives
/usr/local/lib/python3.7/site-packages/matplotlib/mpl-data/stylelib/ggplot.mplstyle
Or more generally you could search for all styles:
find / -iname '*.mplstyle' 2>/dev/null
For Windows I am not really an expert, but maybe the file-paths that were listed above give you a clue where to look.
Python script to install style in the right location
To install your custom styles in the right location, you could build a script that looks something like:
def copy_style():
import os
import matplotlib
# style definition(s)
styles = {}
styles['mystyle.mplstyle'] = '''
font.family : serif
'''
# write style definitions
# directory name where the styles are stored
dirname = os.path.abspath(os.path.join(matplotlib.get_configdir(), 'stylelib'))
# make directory if it does not yet exist
if not os.path.isdir(dirname): os.makedirs(dirname)
# write all styles
for fname, style in styles.items():
open(os.path.join(dirname, fname),'w').write(style)
Yes, it is possible. And you can do it either locally by passing the font to individual labels
font = {'fontname':'your font'}
plt.xlabel('xlabel', **hfont)
plt.ylabel('xlabel', **hfont)
or globally
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'your font'
Try rcParams
matplotlib.rcParams.update({'font.size': 12})
Read more matplotlib

matplotlib show works while savefig fails for unicode

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'

ReportLab Django Not Rendering Chinese Characters

I'm having difficulty making ReportLab render Chinese Characters. From everything I've looked up people are saying that it is probably a font problem but I've used a lot of different fonts and it doesn't even seem to be using them at all. The Chinese characters always just come out as black squares. Below is some sample code of what I have.
# -*- coding: utf8 -*-
from reportlab.lib.pagesizes import letter
from reportlab.pdfbase.ttfonts import TTFont
from io import BytesIO
pdfmetrics.registerFont(TTFont('Arial', 'arial.ttf', 'UTF-8'))
buffer = BytesIO()
doc = SimpleDocTemplate(buffer,
rightMargin=inch*0.5, # 1/2 Inch
leftMargin=inch*0.5, # 1/2 Inch
bottomMargin=0,
topMargin=inch*0.375, # 3/8 Inch
pagesize=letter)
# Get Styles
styles = getSampleStyleSheet()
# Custom Style
styles.add(ParagraphStyle(name='Address', font='Arial', fontSize=8))
elements = []
elements.append(Paragraph(u'6905\u897f\u963f\u79d1\u8857\uff0c\u5927\u53a6\uff03\u5927', styles['Address']))
doc.build(elements)
# Get the value of the BytesIO buffer and write it to the response.
pdf = buffer.getvalue()
buffer.close()
return pdf
I'm using an arial.ttf font found on my Ubuntu 12.04 installation in the fonts folder. I have also tried other fonts installed on this machine and all have exactly the same look even on the numbers and none of the Chinese characters are anything other than black squares.
Am I registering fonts wrong if even the numbers at the beginning aren't printing correctly? What could be causing the black squares?
Solved it. Turns out in your ParagraphStyle it needs to be fontName="Arial" not font="Arial" but I did learn some other tricks of getting it to work in other ways below.
styles.add(ParagraphStyle(name='Address', fontName='Arial')
After doing some digging I've learned a few things that I hope helps someone else in this situation. When you add the tags inside of your Paragraph around the Unicode text and set it explicitly to a font it will work.
elements.append(Paragraph(u'<font name="Arial">6905\u897f\u963f\u79d1\u8857\uff0c\u5927\u53a6\uff03\u5927</font>', styles['Address']))
This fixes the problem at least for Paragraphs with various fonts.
Again this code will work.
Choose the fonts that supports Chinese characters.
In Ubuntu, I choose "AR PL UMing CN" for example.
My code snippets:
# -*- coding: utf-8 -*-
...
pdfmetrics.registerFont(TTFont('AR PL UMing CN', 'uming.ttc'))
styles = getSampleStyleSheet()
...
styles.add(ParagraphStyle(name='Chinese', fontName='AR PL UMing CN', fontSize=20))
elements=[]
elements.append(Paragraph("成”, styles['Chinese']))
doc.build(elements)
...
I can even change to Chinese editor and type in the character straight off. Hope this helps.

Categories