7

I have a question related to using TeX within python.

I have the following packages enabled:

import numpy
import matplotlib
import matplotlib.pyplot as plt

matplotlib.rc('text', usetex = True)
matplotlib.rc('font', **{'family' : "sans-serif"})
params = {'text.latex.preamble' : [r'\usepackage{siunitx}', r'\usepackage{sfmath}']}
plt.rcParams.update(params)

The reason for this can be looked up in a previous question of mine.

However, I would now also be able to use the fonts of the amsmath package. When I include it in params, it does not respond. All I need amsmath for is to label the x-axis of a plot with "a".

So to show you what I have:

enter image description here

and what I want (regarding the x-label):

enter image description here

Please note that to produce the second image, I changed sfmath into amsmath. This immediatly messes up the x- and y-ticks. This is something I do not want to happen.

Is it perhaps possible to change the font style of a single letter/word to that of amsmath? This way I would be able to only use that font style when indicating the x-label of my figure.

A different approach would be to replace sfmath by amsmath in params and make sure the ticks look like the first image.

Thanks

On a side note, the figures were created using:

fig = plt.figure()

ax1 = fig.add_subplot(1, 1, 1)
ax1.set_xlabel(r"$a$", fontsize = 14)

plt.show()
Community
  • 1
  • 1
The Dude
  • 3,795
  • 5
  • 29
  • 47
  • I get your question, but in order to motivate us to find a solution for you: what is wrong with the ticks in the second picture? – Dr. Jan-Philip Gehrcke Jun 25 '14 at 16:04
  • Wrong might be a bit too strong in this case. I do not mind the font. The thing is though that because of `usetex = True` all the ticks are TeX. This makes the ticks thinner. Without increasing their size I would be okey with them if they were slightly bolder. – The Dude Jun 26 '14 at 09:46
  • I added a [new answer](http://stackoverflow.com/a/24432032/1306923) below that appears to do what you want. If it's not quite what you're looking for, could you add a comment with what looks wrong? – tbekolay Jun 29 '14 at 13:13

3 Answers3

8

We can achieve exactly what you're looking for using your second approach: use amsmath and then change the ticklabels to be a different font. This is more of a hack than other answers listed here, but it most closely achieves what you want.

The trick is to use amsmath and let Matplotlib render everything as it normally does, and then at the end, reset the tick labels with the original sans-serif font. I'm not sure if this completely subverts usetex, but if it does, then you have a weird mix of TeX rendered labels and Matplotlib rendered labels. Which looks great!

The important piece of code is

fontProperties = {'family':'sans-serif', 'weight': 'normal', 'size': 12}
ax1.set_xticklabels(ax1.get_xticks(), fontProperties)
ax1.set_yticklabels(ax1.get_yticks(), fontProperties)

Adding this to the end of your script and adding amsmath gives the following:

import numpy
import matplotlib
import matplotlib.pyplot as plt

matplotlib.rc('text', usetex = True)
matplotlib.rc('font', **{'family' : "sans-serif"})
params = {'text.latex.preamble' : [r'\usepackage{siunitx}', r'\usepackage{amsmath}']}
plt.rcParams.update(params)

fig = plt.figure(figsize=(8,6))
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_xlabel(r"$a$", fontsize = 14)

fontProperties = {'family':'sans-serif', 'weight': 'normal', 'size': 12}
ax1.set_xticklabels(ax1.get_xticks(), fontProperties)
ax1.set_yticklabels(ax1.get_yticks(), fontProperties)

Figure

tbekolay
  • 17,201
  • 3
  • 40
  • 38
1

The sfmath package has an option mathitOrig which retains the original font that would be used for math in italics (which is most math in LaTeX). Using this option along with $\mathit{a}$ gives you something close to what you want, though it's not perfect, as the math font is not quite the same as the amsmath font.

import numpy
import matplotlib
import matplotlib.pyplot as plt

matplotlib.rc('text', usetex = True)
matplotlib.rc('font', **{'family' : "sans-serif"})
params = {'text.latex.preamble' : [r'\usepackage{siunitx}', r'\usepackage[mathitOrig]{sfmath}']}
plt.rcParams.update(params)

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_xlabel(r"$\mathit{a}$", fontsize = 14)

With matitOrig

tbekolay
  • 17,201
  • 3
  • 40
  • 38
  • Thanks for your answer. I am aware of `mathitOrig` and have been playing around with it. Also with the other options `sfmath` has. However, none of them produce the "a" I require. – The Dude Jun 26 '14 at 09:17
0

I thought that everything not put into $ ... $ is rendered as normal text. Then we could have just independently defined a text font and a math font. However, the tick labels are affected by the LaTeX math font, as also shown in your question. This is weird, matplotlib somehow wraps all tick labels in a math environment. Hence, the fundamental challenge here is that the tick labels as well as the axis labels are rendered with the same fonts. Now, we could hack around this by making use of multiple math alphabets. Then, you would have to use something like \mathrm{} all over the place.

However, my assumption is that the original problem is that you do not like the tick labels in Computer Modern font. My suggestion therefore is to change the overall font to something that looks great, for the tick labels as well as the axis labels. I have found Linux Libertine to be such a font. I am not 100 % sure about how matplotlib wraps the texts, so therefore I recommend defining text as well as math font, both fitting well together. This can be achieved with the newtx LaTeX package. With lualatex, the preamble can be kept quite clean to achieve what we want and we use a modern tool. According to http://matplotlib.org/users/pgf.html, LuaLaTeX is officially supported for producing PDF figures via the PGF backend. So, this is the code I propose:

import matplotlib as mpl
mpl.use('pgf')
import matplotlib.pyplot as plt

pgf_with_lualatex = {
    "text.usetex": True,
    "pgf.rcfonts": False,   # Do not set up fonts from rc parameters.
    "pgf.texsystem": "lualatex",
    "pgf.preamble": [
        r'\usepackage[libertine]{newtxmath}',
        r'\usepackage[no-math]{fontspec}',
        r'\usepackage{libertine}',
        ]
}
mpl.rcParams.update(pgf_with_lualatex)

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_xlabel("$a b c$", fontsize = 14)
plt.savefig('figure.pdf')

We take absolute control over the fonts by setting rcfonts to False, and by setting text and math fonts in the LaTeX preamble. The no-math option to the fontspec package is required in order to let newtxmath set the math font.

The produced PDF looks good, this is a screenshot:

enter image description here

Dr. Jan-Philip Gehrcke
  • 33,287
  • 14
  • 85
  • 130
  • Thanks for your answer. If I use your code and compare the resulting image with the second image (created using `amsmath`), the ticks are identical. Is there a way to make them bolder? – The Dude Jun 26 '14 at 09:49
  • The ticks are not identical. In your second image they are typeset using Computer Modern font, in my image they are in Libertine. – Dr. Jan-Philip Gehrcke Jun 27 '14 at 13:36