0

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.

enter image description here

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.

Samwise
  • 475
  • 1
  • 4
  • 10

1 Answers1

3

There seems to be no API to change this but you can monkey-patch the appropriate 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()

enter image description here

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()

enter image description here

(For more recent versions of matplotlib, like 3.4.2, this class appears to have been moved to a _mathtext submodule. You may need to do something like the following:)

# Later versions of matplotlib (e.g., 3.4.2)
from matplotlib.mathtext import _mathtext as mathtext

mathtext.FontConstantsBase.sup1 = 0.5

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.

samueldy
  • 75
  • 6
Stop harming Monica
  • 12,141
  • 1
  • 36
  • 56
  • Thanks for this. Does this still work with Times? I see the DejaVuSansFontConstants class in mathtext, but does it also create a FontConstantsBase object for Times New Roman when I specify that font in rcparams? See my image above for the issue with the asterisk superscript. It is quite high and to the right. – Samwise Jan 24 '17 at 23:27
  • Not sure what you mean. `Times` is not a valid option for `mathtext.fontset`. If you want me to replicate and hopefully fix your exact issue you'll have to include all the relevant information in the question. The location of the superscript `*` is consistent with the location of the superscript `b`. – Stop harming Monica Jan 25 '17 at 11:52
  • @Samwise pinging you just in case because I forgot to do it in my previous comment. – Stop harming Monica Jan 25 '17 at 12:03
  • I have updated the example plot code to reflect my changes to the font. My question was how to apply your "monkey-patch" if I am not using dejavusans for my mathtext font. In my example I am using Times New Roman. Thank you. – Samwise Jan 26 '17 at 17:59
  • @Samwise I couldn't test with Times New Roman but I added a paragraph explaining what I think should work. Let me know if it does for you. – Stop harming Monica Jan 26 '17 at 20:17
  • Yes that seems to have worked for the extra subscript spacing. I will have to see about why the asterisk is further to the right for the single superscript case. Thank you. – Samwise Jan 26 '17 at 21:53
  • @Samwise remove unneeded brackets. – Stop harming Monica Jan 26 '17 at 22:48