Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib: Change math font size and then go back to default

I've learned from this question Matplotlib: Change math font size how to change the default size of math text in matplotlib. What I do is:

from matplotlib import rcParams
rcParams['mathtext.default'] = 'regular'

which effectively makes the LaTeX font the same size as the regular font.

What I don't know is how to reset this back to the default behaviour, ie: the LaTeX font looking a bit smaller than the regular font.

I need this because I want the LaTeX font to look the same size as the regular font only on one plot, not on all plots in my figure that use LaTex math formatting.

Here's a MWE of how I create my figure:

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.gridspec as gridspec

# Generate random data.
x = np.random.randn(60)
y = np.random.randn(60)

fig = plt.figure(figsize=(5, 10))  # create the top-level container
gs = gridspec.GridSpec(6, 4)  # create a GridSpec object

ax0 = plt.subplot(gs[0:2, 0:4])
plt.scatter(x, y, s=20, label='aaa$_{subaaa}$')
handles, labels = ax0.get_legend_handles_labels()
ax0.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('A$_y$', fontsize=16)
plt.xlabel('A$_x$', fontsize=16)

ax1 = plt.subplot(gs[2:4, 0:4])
# I want equal sized LaTeX fonts only on this plot.
from matplotlib import rcParams
rcParams['mathtext.default'] = 'regular'

plt.scatter(x, y, s=20, label='bbb$_{subbbb}$')
handles, labels = ax1.get_legend_handles_labels()
ax1.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('B$_y$', fontsize=16)
plt.xlabel('B$_x$', fontsize=16)

# If I set either option below the line that sets the LaTeX font as 'regular'
# is overruled in the entire plot.
#rcParams['mathtext.default'] = 'it'
#plt.rcdefaults()

ax2 = plt.subplot(gs[4:6, 0:4])
plt.scatter(x, y, s=20, label='ccc$_{subccc}$')
handles, labels = ax2.get_legend_handles_labels()
ax2.legend(handles, labels, loc='upper right', numpoints=1, fontsize=14)
plt.ylabel('C$_y$', fontsize=16)
plt.xlabel('C$_x$', fontsize=16)

fig.tight_layout()

out_png = 'test_fig.png'
plt.savefig(out_png, dpi=150)
plt.close()
like image 623
Gabriel Avatar asked Mar 21 '14 20:03

Gabriel


3 Answers

I think this is because the mathtext.default setting is used when the Axes object is drawn, not when it's created. To walk around the problem we need the change the setting just before the Axes object is drawn, here is a demo:

# your plot code here

def wrap_rcparams(f, params):
    def _f(*args, **kw):
        backup = {key:plt.rcParams[key] for key in params}
        plt.rcParams.update(params)
        f(*args, **kw)
        plt.rcParams.update(backup)
    return _f

plt.rcParams['mathtext.default'] = 'it'
ax1.draw = wrap_rcparams(ax1.draw, {"mathtext.default":'regular'})

# save the figure here

Here is the output:

enter image description here

like image 157
HYRY Avatar answered Nov 20 '22 12:11

HYRY


Another solution is to change the rcParams settings to force matplotlib to use tex for all the text (I'll not try to explain it because I only have a vague understanding of this setting). The idea is that by setting

mpl.rcParams['text.usetex']=True

You can pass string literals to any (or most of them?) text defining functions that will be passed to tex, so you can use most of its (dark) magic. For this case, it is enough to use the \tiny, \small, \normalsize, \large, \Large, \LARGE, \huge and \Huge font size size commands

In your MWE case it would be enough to change the second scatter line to

plt.scatter(x, y, s=20, label=r'bbb{\Huge$_{subbbb}$}')

to get a larger subscript font in the legend only in that case. All the other cases are handled correctly straight away

like image 41
mgab Avatar answered Nov 20 '22 11:11

mgab


Here is a nice pythonic way to temporarily change rcParams and automatically change them back again. First we define a context manager that can be used with with:

from contextlib import contextmanager

@contextmanager
def temp_rcParams(params):
    backup = {key:plt.rcParams[key] for key in params}  # Backup old rcParams
    plt.rcParams.update(params) # Change rcParams as desired by user
    try:
        yield None
    finally:
        plt.rcParams.update(backup) # Restore previous rcParams

Then we can use that to temporarily change the rcParams for one specific plot:

with temp_rcParams({'text.usetex': True, 'mathtext.default': 'regular'}):
    plt.figure()
    plt.plot([1,2,3,4], [1,4,9,16])
    plt.show()

# Another plot with unchanged options here
plt.figure()
plt.plot([1,2,3,4], [1,4,9,16])
plt.show()

Result:

Two example plots with different fonts

like image 33
Fritz Avatar answered Nov 20 '22 11:11

Fritz