matplotlibで上付き文字が上過ぎ、下付き文字が下過ぎる問題の解決

環境：
Ubuntu 18.04.5 LTS (Windows Subsystem for Linux)
Python 3.6.9
Matplotlib 2.1.1

※matplotlibのバージョン3.4.2以降で、mathtextのクラスが_mathtextサブモジュールに移動していました。とのコメントをいただき、本文に追記しました。
ご指摘いただきありがとうございました。

# 問題点

matplotlibのmathtextはもともと数式用のためか、フォントによっては上付き文字が上過ぎ下付き文字が下過ぎる。

例えば、以下のようにTimes New Romanを使った場合、

```python

import matplotlib.pyplot as plt

plt.rcParams.update({'mathtext.default': 'default',
                     'mathtext.fontset': 'stix',
                     'font.family': 'Times New Roman',
                     'font.size': 12,
                     'figure.figsize': (3, 3)})

plt.text(0.5, 0.9, '$NH_4^{+}$',    ha='center', va='center')
plt.text(0.5, 0.7, '$SO_4^{2{-}}$', ha='center', va='center')
plt.text(0.5, 0.5, '$H_2O$',        ha='center', va='center')
plt.text(0.5, 0.3, '$(cm^{{-}1})$', ha='center', va='center')
plt.text(0.5, 0.1, '$(s^{{-}1})$',  ha='center', va='center')
plt.savefig('default.png')
plt.show()
```
このような図(default.png)が生成される。
![default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477781/05bdcd2f-57a8-958f-9410-0c584c514ae4.png)


以下の解決策を施せば、生成される図は、
![cmfc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477781/fe9dcc15-4747-ce1d-d2b9-428ca4d4b084.png)

このようになる。

# 解決策

上付き・下付き文字をちょうど良い位置に付けるには、Matplotlibのバージョンに応じ、以下のいずれかの2行を加えて、

```python
# Matplotlib 3.4.2より前の場合
from matplotlib import mathtext
mathtext.FontConstantsBase = mathtext.ComputerModernFontConstants
```

```python
# Matplotlib 3.4.2以降の場合
from matplotlib import _mathtext as mathtext
mathtext.FontConstantsBase = mathtext.ComputerModernFontConstants
```

FontConstantsBaseの中身をComputerModernFontConstantsの設定値に変更する。
すなわち、例えば、


``` python

import matplotlib.pyplot as plt
from matplotlib import mathtext

mathtext.FontConstantsBase = mathtext.ComputerModernFontConstants

plt.rcParams.update({'mathtext.default': 'default',
                     'mathtext.fontset': 'stix',
                     'font.family': 'Times New Roman',
                     'font.size': 12,
                     'figure.figsize': (3, 3)})

plt.text(0.5, 0.9, '$NH_4^{+}$',    ha='center', va='center')
plt.text(0.5, 0.7, '$SO_4^{2{-}}$', ha='center', va='center')
plt.text(0.5, 0.5, '$H_2O$',        ha='center', va='center')
plt.text(0.5, 0.3, '$(cm^{{-}1})$', ha='center', va='center')
plt.text(0.5, 0.1, '$(s^{{-}1})$',  ha='center', va='center')
plt.savefig('cmfc.png')
plt.show()
```
これを実行して、生成された図(cmfc.png)は先程の
![cmfc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477781/fe9dcc15-4747-ce1d-d2b9-428ca4d4b084.png)





# 説明



mathtext.FontConstantsBaseで設定されている下付き・上付き文字(sub/superscripts)の仕様とそれらの初期値は、

```python

    # 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
```

ここで、x-heightは大文字"X"の高さ、baselineは"j"や"g"などの下端の位置に対応するようである。

一方、mathtext.ComputerModernFontConstantsの設定値は、

```python

    script_space = 0.075
    subdrop = 0.2
    sup1 = 0.45
    sub1 = 0.2
    sub2 = 0.3
    delta = 0.075
    delta_slanted = 0.3
    delta_integral = 0.3
```

各項目を個々に設定したければ、mathtextをインポートした後、

```python

mathtext.FontConstantsBase.delta = 0.01
```

のようにする。

#追伸

私はいつも、

```python

from matplotlib import mathtext
mathtext.FontConstantsBase = mathtext.ComputerModernFontConstants
mathtext.FontConstantsBase.script_space = 0.01
mathtext.FontConstantsBase.delta = 0.01
```
として、
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477781/81b328e4-0f33-b91d-10e5-54bdf4e234b3.png)

のようにしている。

因みに、

```latex

$SO_4^{2{-}}$
$NH_4^{+}$
```
のように+や-を{}で括るのは、演算子の前後に自動で挿入されるスペースを排除するためである。