-->

Matplotlib 2.0 subscript outside of baseline when

2019-09-16 08:18发布

问题:

With matplotlib 2.0 I have been having strange behavior when I use both subscript and superscript on the same character. When they are combined, the subscript goes down entirely below the baseline. This didn't happen with MPL 1.5. Here is a complete example:

import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc("font", family="Times New Roman",weight='normal')
plt.rcParams.update({'mathtext.default':  'regular' })
plt.plot(1,1, label='$A_x^{b}$')
plt.plot(2,2,label='$A_x$')
plt.plot(3,3,label='$A^b$')
plt.plot(4,4,label='$A_x^{*}$')
plt.plot(5,5,label='$A^*$')
plt.legend(fontsize='xx-large')
plt.show()

I've taken this plot and zoomed in on the legend and drawn some horizontal lines to show the relative super and subscript positions.

I found in the mathtext.py file these parameters under the class FontConstantBase:

# Percentage of x-height of additional horiz. space after sub/superscripts
script_space = 0.05

# Percentage of x-height that sub/superscripts drop below the baseline
subdrop = 0.4

# Percentage of x-height that superscripts are raised from the baseline
sup1 = 0.7

# Percentage of x-height that subscripts drop below the baseline
sub1 = 0.3

# Percentage of x-height that subscripts drop below the baseline when a
# superscript is present
sub2 = 0.5

# Percentage of x-height that sub/supercripts are offset relative to the
# nucleus edge for non-slanted nuclei
delta = 0.025

# Additional percentage of last character height above 2/3 of the
# x-height that supercripts are offset relative to the subscript
# for slanted nuclei
delta_slanted = 0.2

# Percentage of x-height that supercripts and subscripts are offset for
# integrals
delta_integral = 0.1

Did sub2 exist in previous versions? Could going from 0.3 to 0.5 really drop it completely below the baseline like I'm seeing? I'd like to have simultaneous superscripts and subscripts that aren't completely outside the baseline and I don't see any other way besides modifying mathtext.py itself. Also, it appears that when including an asterisk in the superscript, it also goes higher than anticipated with mpl 2.0. Is there a way to lower it down just a bit without changing mathtext? Thanks.

回答1:

There seems to be no API to change this but you can monkey-patch the apropiate class instead of editing mathtext.py.

Using the default mathtext font the position of the subscript changes if there is a superscript (not totally under the baseline but you can see the effect):

def test_plot():
    plt.figure()
    plt.plot(1,1, label='$A_x^b$')
    plt.plot(2,2,label='$A^b_x$')
    plt.plot(3,3,label='$A_x$')
    plt.plot(4,4,label='$A_x^*$')
    plt.plot(4,4,label='$A^*_x$')
    plt.plot(5,5,label='$A^*$')
    plt.legend(fontsize='xx-large')

# default mathtext font in matplotlib 2.0.0 is 'dejavusans'
# set explicitly for reproducibility
plt.rcParams['mathtext.fontset'] = 'dejavusans'
test_plot()

Monkey-patching mathtext.DejaVuSansFontConstants you can make the effect disappear:

import matplotlib.mathtext as mathtext
mathtext.DejaVuSansFontConstants.sub2 = 0.3  # default 0.5
test_plot()

I can't see any issue with the asterisk.

I don't have Times New Roman installed so I can't test your exact use case but probably you need to patch FontConstantsBase instead of DejaVuSansFontConstants. It worked for me using Liberation Serif.