Reputation: 20196
Can I get nice latex-style printing of sympy's geometric algebra objects in the ipython notebooks?
In the ipython
notebook, I can get pretty printing of various mathematical objects from sympy
. For example, if my sympy
variables are Greek characters, the output is printed beautifully as latex. (Presumably using MathJax...) An explicit example:
from sympy import symbols, init_printing
init_printing(use_latex=True)
alpha = symbols('alpha')
alpha**2/3
The output is a nicely displayed fraction à la latex, with a correctly placed superscript and a true alpha. Perfect.
But I also do a lot of work with the geometric algebra module sympy.galgebra.GA
, and I'd like similar results. Apparently, there's a different printing system called latex_ex
for this module, and it does seem to work when I run scripts (like those on the module's page) from the command line and have them output dvi files. But nothing I do makes the GA come out looking nice in the notebook. Is there anything I can do?
Just to be specific, here's a concrete example:
from sympy.galgebra.GA import *
metric = '1 0 0,0 1 0,0 0 1'
gamma_x,gamma_y,gamma_z = MV.setup('gamma_x gamma_y gamma_z',metric,True)
gamma_x
The output is just the repr
of gamma_x
, which is something unhelpful like <sympy.galgebra.GA.MV at 0x1060b8510>
. Similarly, calling print
just gives me _1*gamma_x
, which is what I'm trying to avoid.
In a script, I can add the following to the above:
from sympy.galgebra.latex_ex import LatexPrinter, xdvi
LatexPrinter.format(1,1,1,1)
print gamma_x
xdvi(filename='testGA.tex')
This gives me the expected DVI with nice latex expressions. Of course, if I do the same thing in the notebook, I get absolutely no output for any print statement, even those not involving GA objects -- literally nothing, not just non-pretty stuff.
I'm running python 2.7.5, with sympy 0.7.3, and using a notebook under ipython 1.0.
Since various changes have been made in the workings, I've had to make various changes. I collect a nice current example in my answer.
I've actually gotten a very ugly hack to work with the current release versions of the code. The following does the job, but I'm very dissatisfied, so I'm hopeful that Alan's new version of the module will lead to better things. This is here for reference, mostly. But the basic idea seems to be that sympy.galgebra.GA.MV._repr_latex_
will need to be defined somehow. Anyone with deeper knowledge of sympy or ipython's workings is more than welcome to comment.
from sympy.galgebra.GA import *
metric = '1 0 0,0 1 0,0 0 1'
gamma_x,gamma_y,gamma_z = MV.setup('{\gamma}_x {\gamma}_y {\gamma}_z',metric,True)
def MVlatex(mv, *args) :
from re import sub
s = str(mv)
s = s.replace('*',r' ')
s = sub(r'(?<![}_a-zA-Z0-9])_1(?![a-zA-Z0-9])', r' ', s)
s = sub(r'__([a-zA-Z0-9]*)', r'^{\1}', s)
s = sub(r'_([a-zA-Z0-9]*)', r'_{\1}', s)
return '$$'+s+'$$'
sympy.galgebra.GA.MV._repr_latex_ = MVlatex
gamma_x
Note the unfortunate use of regexes, with negative lookbehinds, etc. Also, _repr_latex_
sometimes gets multiple arguments. I don't know what any argument but the first means, so I just throw them away. Finally, I'm sure there are plenty of things that still come out very ugly; this is just the result of my initial rough try.
Upvotes: 2
Views: 2304
Reputation: 20196
The current git version has newer code and very different syntax. I've made a pull request containing the last piece of code needed to make this fully work with ipython notebook. So, hopefully, none of the following will be necessary in the near future.
The following is a MWE of what I've been using with more recent versions of sympy (I currently use sympy version 0.7.5-git with ipython notebook version 2.0.0-dev).
# Some generic startup stuff
import sympy, sympy.galgebra.ga
metric = '1 0 0,0 1 0,0 0 1'
gamma_x,gamma_y,gamma_z = sympy.galgebra.ga.MV.setup('gamma_x gamma_y gamma_z',metric)
# Setup nice printing for the notebook
sympy.init_printing()
sympy.galgebra.ga.Format(ipy=True)
def MVlatex(mv, *args) :
mv.base_to_blade()
return '$$'+str(mv).replace(r'\W', r'\wedge').replace(r'\bm', r'\boldsymbol').replace(r'\lp',r'\left(').replace(r'\rp',r'\right)')+'$$'
sympy.galgebra.ga.MV._repr_latex_ = MVlatex
# Show a couple examples
display(gamma_x ^ gamma_y)
display( 3*gamma_x*gamma_y/2 + (gamma_z^gamma_x) )
Presumably, the relevant section should actually get merged into the galgebra code. In particular, the tex macro definitions for \W
, \lp
, \rp
, etc., are never seen by mathjax, and \bm
is not compatible with mathjax, so those must be changed. Also, the function _repr_latex_
needs to be defined in the MV
class.
I'll also note that for other classes where you can't dynamically add attributes (_repr_latex_
in this case), you can still tell ipython to use your function to do the display with something like
ip = get_ipython()
latex_formatter = ip.display_formatter.formatters['text/latex']
latex_formatter.for_type_by_name('sympy.galgebra.ga', 'MV', MVlatex)
Upvotes: 1
Reputation: 141
I am doing another major rewrite to galgebra which solves many of the Ipython/LaTeX problems. It will be added to my sympy github repository as soon as I can converts the LaTeX documentation I had written for it to python-sphinx. If you are impatient go to github.com/brombo/GA and look at GA.pdf in LaTeX docs. The reason that a major rewrite was required was because in order to do manifolds/submanifolds correctly one need to have multiple instantiations of geometric algebras which is impossible in the current implementation. This is because a submanifold has it's own geometric algebra which is different from the base manifold. The new implementation also includes a differential operator class with left and right grad operators (see documentation). When finished (sort of) the new implementation also has a multilinear transformation class which can be used for concrete symbolic tensors (indices are not needed).
Upvotes: 1
Reputation: 151
This works for me.
import sympy
import sympy.galgebra
import sympy.galgebra.printing
sympy.galgebra.ga_print_on()
sympy.galgebra.ga.Format(ipy=True)
sympy.init_printing(use_latex=True)
def MVlatex(mv, *args) :
from re import sub
s = str(mv)
s = sub(r'\\W',r'\\wedge', s)
s = sub(r'\\bm',r'\\mathbf', s)
return '$$'+s+'$$'
sympy.galgebra.ga.MV._repr_latex_ = MVlatex
Upvotes: 1
Reputation: 141
I am the author of the GA module a I will look into the Ipython latex problem. I strongly suggest that you use the latest version of sympy which has a new version of GA. Look at the new documentation as to how to use the new GA. Several things have changed. Try the following (I don't know if it will work since I don't use Ipython myself). For the "Format" statement use
Format(ipy=True)
and see if it works (again look at documenatation and examples with the new distribution for other things have changes with printing and other aspectes of the module). My development method it to write scripts using the "geany" editor. Then I can just press the run button on the editor and observe the output either terminal or latex.
I am interested in what you are using GA for and finding out what you would want to be included in future versions. If you wish to contact me directly my Email is
Upvotes: 3