Matplotlib seeing new font but not applying it, xkcd mode - matplotlib

I'm trying to get Matplotlib's xkcd style to use the font designed for it, Humor Sans.
I'm getting Comic Sans instead, see pic
Now, the point is about the correct font not getting recognised here, I have removed the cache as per here and as suggested in the same question. Basically what is suggested in this other question.
I have even "forced" Matplotlib to regenerate the font cache as
f = matplotlib.font_manager.FontManager()
and looks like the desired font is there:
f.findfont("Humor Sans")
'/Users/myname/Library/Fonts/Humor-Sans.ttf'
So I don't get why the plot still shows Comic Sans? It has been obtained with code
plt.xkcd()
plt.plot([i for i in range(10)], np.sin([i for i in range(10)]))
plt.title('A sine wave')
plt.show()
I even tried changing backend as per this Q&A, to no avail.

The solution was to also clear the cached font_manager instance, as
rm ~/.matplotlib/fontList.py3k.cache

Related

Matplotlib does not find basic fonts

I am trying to use Computer Modern (i.e. the standard LaTeX font) in my pyplot figures, however, I get the error
findfont: Font family ['serif'] not found. Falling back to DejaVu Sans.
All I do is:
from matplotlib import rc
rc('text', usetex=True)
rc('font', **{'family': 'serif', 'serif': ['Computer Modern']})
I have also found this thread which dealt with the same issue, however, I cannot install the packages mentioned in the answer there because I am not an admin on the machine I am using. Deleting the matplotlib cache did not help, either. I have located the font, though:
~/.local/lib/python3.6/site-packages/matplotlib/mpl-data/fonts/
which has the subfolders afm and ttf (and another one), and within both of them, I find files like
cmr10.afm
or
cmr10.ttf
so the fonts are actually installed on the computer. The fontlist-v330.json file links to
"fname": "fonts/afm/cmr10.afm"
for Computer Modern. I have tried manually changing this to the ttf file, and I have also tried giving it the full path, but to no avail. At this point, I am at a loss for ideas. How can I solve this issue?
All you need to do should be using the actual name of the font file:
from matplotlib import rc
rc('text', usetex=True)
rc('font', **{'family': 'serif', 'serif': ['cmr10']})

Using matplotlib with latex mode with non-default fonts

I am using Windows 10 with Anaconda and Spyder 4. When using matplotlib, I would like to use the font Proxima Nova and render with LaTeX.
If in my matplotlibrc file I specify
font.family : Proxima Nova
then the figure renders with the font Proxima Nova. This means that the font is installed on my system (as it is) and matplotlib can use it. However, if in the matplotlibrc file I also specify
text.usetex: True
then, even though I have specified Proxima Nova as the font, the figure renders in the default LaTeX font, which I guess is Computer Modern.
I have tried
matplotlib.font_manager._rebuild()
In the source code file and also have tried specifying the fonts in the source code file and not in the matplotlibrc file. However I always get the same result. I have also followed all the advice on this help page, including making sure that latex, dvipng and ghostscript are all the PATH variable. However nothing seems to work.
I would like to note that I can use Proxima Nova separately when compiling Latex documents, so that should not be an issue either.
How can I get matplotlib to be able to use a non-default font and render with LateX at the same time?
After some further investigation, I was able to get to use Proxima Nova with Latex, although there are still some outstanding issues.
The main issue is that if the font Proxima Nova is used with Latex, one needs to use Lualatex and not plain Latex. Here is the Matplotlib instruction on using matplotlib with Lualatex.
The key to getting things to work was this post.
At the very beginning of my .py file, I have the following code:
import matplotlib as mpl
mpl.use("pgf")
mpl.rcParams.update({
'font.family': 'sans-serif',
'text.usetex': True,
'pgf.rcfonts': False,
'pgf.texsystem': 'lualatex',
'pgf.preamble': r'\usepackage{fontspec} \setmainfont{Proxima Nova}',
})
The code above should be placed at the very top of the code, above any other imports.
The problem, however is that this solution works only after performing the following steps:
Delete the .matplotlib/tex.cache folder and restart spyder
Replace 'font.family': 'sans-serif' and \setmainfont{Proxima Nova} with 'font.family': 'serif' and \setmainfont{Times New Roman} respectively. Run python once.
Revert back to 'font.family': 'sans-serif' and
\setmainfont{Proxima Nova} and run python again.
The output with the correct font is produced.
Unless the above 4 steps are performed, the output is compiled with the default DejaVu Sans font and not with Proxima Nova. I am not sure why...
After getting help on the matplotlib github forum, I was pointed to the following solution:
mpl.rcParams.update({
'font.family': 'sans-serif',
'text.usetex': True,
'pgf.rcfonts': False,
'pgf.texsystem': 'lualatex',
'pgf.preamble': r'\usepackage{fontspec} \setsansfont{Proxima Nova}',
})
In other words you need to use setsansfont in stead of setmainfont. You can see the matplotlib forum page here.

Transparent inline matplotlibs in IPython

I'd like the background of my matplotlib plots to be transparent in my IPython notebook. This may sound silly because the notebook itself defaults to a white background but:
1) I use a solarized background and
2) more importantly, I want them to be transparent for when I embed the notebook directly into my blog via nbconvert.
It's easy enough to use something like savefig('file', transparent=True) , but I'm not saving the figures, I am displaying them inline (by calling IPython with ipython notebook --matplotlib inline.
I've been playing around with the IPython notebook configuration file, especially with c.InlineBackend.rc. For example, I upgraded to the dev version of matplotlib to get access to its new savefig.transparent rcParam, and tried configuring that with c.InlineBackend.rc = {'savefig.transparent': True}, but as expected it only affects plots saved with savefig.
Note that I am using the recent IPython 2.0 release. This must be possible somehow, right? Any light that you can shed would be appreciated.
Just to follow up, the issue opened on Github by tillsten has been patched so something like this:
rcParams['figure.facecolor'] = (0,0,0,0)
should work now after you update IPython. Three cheers for open source.
The inline plots are html objects (<img>) with class ui-resizable. So you can change their default behavior by customizing the CSS for your notebooks:
locate your settings for notebooks: in a terminal, type
ipython locate
in the indicated directory, go to subdir profile_default\static\custom (or any profile you want to use instead)
edit or create a CSS file named custom.css
put this in it:
img.ui-resizable
{
opacity:0.4;
}
Close your notebooks, kill IPython and restart it (so that it recreates the served files).
It should work with exported notebooks, as long as you export them as html and you change the css there too.
It's not exactly what you want, but it does the job.

Can I distribute just one extra font file with a matplotlib application?

I’m writing a Python program that uses matplotlib. I’d like to use a font that isn’t included with matplotlib. (Well, I want to use Lucida Grande, which is included in OS X, but matplotlib can’t read the .dfont file directly so I need to distribute my own .ttf font.)
It seems like matplotlib only ever looks in one directory for fonts: mpl-data/fonts. It’s possible to tweak matplotlib’s configuration to change where the mpl-data directory is, but it doesn’t seem to be possible to specify more than one such directory in which fonts may be found. Is that accurate?
(It would be possible for me to put the font in my system’s global mpl-data directory, but it feels wrong for an application to muck around with a globally-used directory like that. And I sure as hell don’t want to include the entire mpl-data-plus-one-file with my application.)
One possibility is to expand on the response provided here which uses the matplotlib font manager module. Specifically, it looks like you can specify the absolute path to your font with the fname argument to matplotlib.font_manager.FontProperties (see the docs here: http://matplotlib.org/api/font_manager_api.html#matplotlib.font_manager.FontProperties)
Modifying the previous SO response (to a slightly simpler question) below, this is certainly worth a try if you can specify the absolute path to the ttf font file in your workflow. I've used a built-in MacOS font below (and that works), but maybe try substituting your particular absolute path & font to see if it works.
import matplotlib
matplotlib.use( "agg" ) #some backend sensitivity explained in previous SO response
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
fig, ax = plt.subplots()
#specify the absolute path to your font file:
absolute_path_to_ttf_file = '/opt/X11/share/fonts/TTF/VeraSe.ttf'
prop = fm.FontProperties(fname=absolute_path_to_ttf_file)
ax.set_title('Text in a cool font', fontproperties=prop, size=40)
plt.show()
plt.savefig('test.png')

Matplotlib uses broken pdfmarks in latex

I have a really weird problem:
plt.xlabel("$t$[ms]")
plt.ylabel("$\dot{q}$[deg]")
plt.axvline(x=span2Stop,lw='0.3',c='0.5')
plt.axvspan(spanStart, spanStop, facecolor='0.9', alpha=1,edgecolor='0.9',lw=0)
plt.annotate('11ms',fontsize='9', xy=(11, -500),xytext=(2, -500),verticalalignment='center',arrowprops=myarrow)
plt.annotate('13ms',fontsize='9', xy=(13, 1000),xytext=(2, 1000),verticalalignment='center',arrowprops=myarrow)
plt.annotate('17ms',fontsize='9', xy=(17, -500),xytext=(20, -500),verticalalignment='center',arrowprops=myarrow)
plt.tight_layout()
plt.savefig(imagePath + "snapAHVjoints.pdf")
plt.savefig(imagePath + "snapAHVjoints.svg")
plt.show()
generates a nice looking picture. But plt.axvline(x=span2Stop,lw='0.3',c='0.5') causes a broken pdfmark in the exported pdf if included in latex as a pdf. I spent ages to find that.
Compiled with xelatex to pdf. The problem does not seem to be related to the loaded packages (to be honest I didn't try to to disable hyperref but tested almost all options I found).
Any Idea what's wrong with that?
lw='0.3' should be lw=0.3 Nevertheless, no broken pdf should be exported. If you export it as eps matplotlib complains, so I recognized it that way
Is that a bug or am I again getting wrong soem pythonic things?