32

The font of the axis tick mark labels produced from the following code isn't Helvetica, but is still the default serif Computer Modern. Any suggestions are greatly appreciated.

from matplotlib import rc, font_manager
from numpy import arange, cos, pi
from matplotlib.pyplot import figure, axes, plot, xlabel, ylabel, title, \
grid, savefig, show

sizeOfFont = 12
fontProperties = {'family':'sans-serif','sans-serif':['Helvetica'],
    'weight' : 'normal', 'size' : sizeOfFont}
ticks_font = font_manager.FontProperties(family='Helvetica', style='normal',
    size=sizeOfFont, weight='normal', stretch='normal')
rc('text', usetex=True)
rc('font',**fontProperties)
figure(1, figsize=(6,4))
ax = axes([0.1, 0.1, 0.8, 0.7])
t = arange(0.0, 1.0+0.01, 0.01)
s = cos(2*2*pi*t)+2
plot(t, s)

for label in ax.get_xticklabels():
    label.set_fontproperties(ticks_font)

for label in ax.get_yticklabels():
    label.set_fontproperties(ticks_font)

xlabel(r'\textbf{time (s)}')
ylabel(r'\textit{voltage (mV)}',fontsize=16,family='Helvetica')
title(r"\TeX\ is Number $\displaystyle\sum_{n=1}^\infty\frac{-e^{i\pi}}{2^n}$!",
    fontsize=16, color='r')
grid(True)
savefig('tex_demo.pdf')

show()
5
  • Are you sure you have installed Helvetica font correctly? I think on my laptop the font showing up is sans-serif Helvetica... Commented Sep 7, 2012 at 17:34
  • I assume that its installed correctly because the axis labels are in Helvetica. In the example, the equation and the tick labels are Computer Modern, but everything else is Helvetica. Commented Sep 7, 2012 at 18:18
  • Okay, thanks. I misunderstood what you were asking... Commented Sep 7, 2012 at 18:22
  • Are the tick labels Helvetica on your machine? Commented Sep 7, 2012 at 18:28
  • Any good answer on this is still missing ... unfortunately. Commented Feb 29, 2024 at 1:43

4 Answers 4

24

I think the confusion here stems from the fact that you're mixing TeX and non-TeX font commands.

This turns on TeX mode, so all of the text is rendered with an external TeX installation:

rc('text', usetex=True)

In this line, setting it to sans-serif will get passed along to TeX, but a specific ttf font name can not be used by TeX, so the second part (involving Helvetica) is ignored. And setting the default body text in TeX does not (by default) change the math font. This is (unfortunately standard TeX behavior).

rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})

This affects the font set used by matplotlib's internal mathtext renderer, and has no effect on TeX:

rc('mathtext', fontset='stixsans')

The solution I use when I want all sans-serif out of TeX is to use the cmbright package, which can be turned on by adding:

rc('text.latex', preamble=r'\usepackage{cmbright}')

That may require installing the cmbright LaTeX package if you don't already have it.

Sign up to request clarification or add additional context in comments.

Comments

22

Okay, this worked for me. Replace the following lines:

for label in ax.get_xticklabels():
    label.set_fontproperties(ticks_font)

for label in ax.get_yticklabels():
    label.set_fontproperties(ticks_font)

with this:

from matplotlib.pyplot import gca
a = gca()
a.set_xticklabels(a.get_xticks(), fontProperties)
a.set_yticklabels(a.get_yticks(), fontProperties)

What you did in your original code makes sense to me, but I get different results this way. Weird.

5 Comments

No error, but doesn't work either. Is there anything you have to define before or after this? Anything that might overwrite this setting?
@DrunkenMaster the code still works for me. What wasn't clear in my original answer was that the function gca needed to be imported explicitly because the original code in the question did not do so.
This unfortunately changes the power notation to scalar notation in log axes, and it is unclear to me how it can be restored while still maintaining the tick font. Any ideas?
It's been a while since this answer was written, but for log axes, this might be a better starting point: stackoverflow.com/a/21920673/515392. If you get a handle to an axis object, it may have a way to set font properties with that object.
I explain the reason why this seems to work in my answer. It is not a very good idea to do this however.
13

I just found a little simple way you can try. Just call the .xticks method and give the fontname as user-set argument.

e.g.

import matplotlib.pyplot as plt
plt.figure()
#... do the plot you want...
plt.yticks(fontname = "Times New Roman")  # This argument will change the font.
plt.show()

Comments

1

If you print out ax.get_xticklabels(), it should be clear what is going on.

[Text(-0.2, 0, '$\\mathdefault{−0.2}$'),
 Text(0.0, 0, '$\\mathdefault{0.0}$'),
 Text(0.2, 0, '$\\mathdefault{0.2}$'),
 Text(0.4000000000000001, 0, '$\\mathdefault{0.4}$'),
 Text(0.6000000000000001, 0, '$\\mathdefault{0.6}$'),
 Text(0.8, 0, '$\\mathdefault{0.8}$'),
 Text(1.0000000000000002, 0, '$\\mathdefault{1.0}$'),
 Text(1.2000000000000002, 0, '$\\mathdefault{1.2}$')]

The tick labels are rendered with the LaTeX code

$\mathdefault{...}$

As such, one way is to redefine the \mathdefault command.

rc('text.latex', preamble=r'\def\mathdefault{\mathsf}')

Another way is to use StrMethodFormatter (credit), but this seems like a bad idea because it throws away all the hard work done by ScalarFormatter.

from matplotlib.ticker import StrMethodFormatter
formatter=StrMethodFormatter('$\\mathsf{{{x:.3g}}}$')
ax.xaxis.set_major_formatter(formatter)
ax.yaxis.set_major_formatter(formatter)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.