ob-ipython で sympy を使うときに出力を綺麗にする

jupyter notebook で sympy を使うとセルの実行結果を Latex で表示してくれるので便利だが、 ob-ipython で sympy を使うとセルの実行結果の表示が jupyter notebook ほど便利でない。

#+BEGIN_SRC ipython :session :exports both :results output raw drawer
from sympy import *
init_printing()

x = symbols("x")
eqn = Eq(x**2+3*x-4)
print(latex(eqn))
#+END_SRC

#+RESULTS:
:RESULTS:
x^{2} + 3 x - 4 = 0
:END:
from sympy import *
init_printing()

x = symbols("x")
eqn = Eq(x**2+3*x-4)
print(latex(eqn))

x2 + 3 x - 4 = 0

幸い org-babel には「src block の実行結果を別の src block に通して、その結果を元の src block の結果にする」 という機能があるので、その機能を使えばこの問題を回避した。

引数付きの src block は emacs lisp だと書きやすいので、それを使って書いた。 sympy の出力にエスケープされたカッコをつけて MathJax のソースコードとして認識されるようにした。

#+name: wrapper-latex
#+begin_src emacs-lisp :var text="" :exports none
(concat "\\(" (replace-regexp-in-string "\n$" "" text) "\\)\n")
#+end_src

#+HEADER: :session :exports both :results output drawer
#+HEADER: :eval no-export :post wrapper-latex(text=*this*)
#+BEGIN_SRC ipython
x = symbols("x")
y = symbols("y", cls=Function)

eqn = Eq(y(x).diff(x), sin(x)*tan(y(x)))
print(latex(eqn))
#+END_SRC

#+RESULTS:
\(\frac{d}{d x} y{\left (x \right )} = \sin{\left (x \right )} \tan{\left (y{\left (x \right )} \right )}\)
x = symbols("x")
y = symbols("y", cls=Function)

eqn = Eq(y(x).diff(x), sin(x)*tan(y(x)))
print(latex(eqn))

\(\frac{d}{d x} y{\left (x \right )} = \sin{\left (x \right )} \tan{\left (y{\left (x \right )} \right )}\)

だいぶ良くなった。

次に数式の最初に \displaystyle をいれ、さらに数式全体を special block で囲んで見やすくした。

#+name: wrapper-latex2
#+begin_src emacs-lisp :var text="" :exports none
(concat "#+BEGIN_exa\n\\(\\displaystyle"
        (replace-regexp-in-string
         "# Out\\[.*\\]:\n: '\\(.*\\)'"
         "\\1"
         text)
        "\\)\n#+END_exa")
#+end_src

#+HEADER: :session :exports both :results value raw
#+HEADER: :eval no-export :post wrapper-latex2(text=*this*)
#+BEGIN_SRC ipython
x = symbols("x")
y = symbols("y", cls=Function)

eqn = Eq(y(x).diff(x), (x-2*y(x)+3)/(2*x+y(x)-4))
latex(eqn)
#+END_SRC

#+RESULTS:
#+BEGIN_exa
\(\displaystyle\\frac{d}{d x} y{\\left (x \\right )} = \\frac{x - 2 y{\\left (x \\right )} + 3}{2 x + y{\\left (x \\right )} - 4}\)
#+END_exa
x = symbols("x")
y = symbols("y", cls=Function)

eqn = Eq(y(x).diff(x), (x-2*y(x)+3)/(2*x+y(x)-4))
print(latex(eqn))

\(\displaystyle\frac{d}{d x} y{\left (x \right )} = \frac{x - 2 y{\left (x \right )} + 3}{2 x + y{\left (x \right )} - 4}\)

さらに src block を実行するたびに latex 要素を画像として表示するようにした。 使い勝手が jupyter notebook にかなり近くなった。

(add-hook 'org-babel-after-execute-hook 'org-toggle-latex-fragment)

参考

Header arguments - Org Babel reference card