matplotlibでtexコマンドとformatを組み合わせるときにハマった話
要約
matplotlibでtexコマンドとstr.format()
メソッドを併用した次のコードで問題が発生しました.
title = r'\texttt{shape}, $\mathrm{eps} = {eps}$'.format(shape=shape, eps=eps)
これを次のように書き換えて解決しました.
title = r'\texttt {shape}, $\mathrm{{eps}} = {eps:.0e}$'.format(shape=shape, eps=eps)
1. はじめに
pythonには文字列メソッド str.format()
が用意されています.
数値や文字列を様々な書式に変換してくれるメソッドです.
例えば,1.2345 → 1.2 という変換を行いたいとき.
print("{num:.2}".format(num=1.2345)) >> 1.2
引数を指定できるのが便利ですよね.
format
の詳しい使い方はこちらで解説されています.
2. 問題と解決策
pythonで図を作るときにmatplotlibを使っています.
で,この図のタイトルを付けるときにハマりました.
matplotlibではグラフのラベルやタイトルを付けるときにtex記法が使えます.
texコマンドは\command{str}
という感じで使いますが,この {}
と先ほど紹介した'{}'.format()
がケンカしました.
コード
title = r'\texttt{shape}, $\mathrm{eps} = {eps}$'.format(shape=shape, eps=eps) ax.set_title(title, fontsize=40)
エラー
RuntimeError: latex was not able to process the following string: b'\\\\textttsmooth, $\\\\mathrm0.0001 = 0.0001$'
どうやら,format
メソッドによって\texttt{shape}
の{}
が展開されて,\textttshape
になってしまったようですね.
後ろも同じように,\mathrm0.0001
になっていますね.
2.1 解決策
前者ではformat
によって代入された文字列を\texttt
に渡して欲しい.
\texttt
と{shape}
の間にスペースを挟んで,\texttt {shape}
としたら解決しました.
後者では eps = 1e-4
と表示されて欲しい.
\mathrm{eps}
のeps
をformat
の引数ではなく,単なる文字列として扱われるように,\mathrm{{eps}}
としてあげれば解決ですね.- 一桁の指数表示にしたいので,
\mathrm{{eps:.0e}}
とすれば希望の表示になりそうです.
最終的に以下のコードで下の図の生成に成功しました.
(引数名変えたり$$
外せばいいんですけどね...)
fig = plt.figure() ax = plt.subplot(111) arx = np.linspace(0, 2*np.pi, 100) ary = np.array([np.cos(x) for x in xx]) ax.plot(arx, ary) eps = 0.0001 shape = 'smooth' title = r'\texttt {shape}, $\mathrm{{eps}} = {eps:.0e}$'.format(shape=shape, eps=eps) ax.set_title(title, fontsize=40)
3. まとめ
texコマンドと'{str}'.format
メソッドを組み合わせるときの注意点と解決策は以下のとおりです.
texコマンドの{}
内の文字と,format
メソッドの引数名を同名にすると展開されてコマンド名の一部になる