Mike
Mike

Reputation: 20196

Nice output for geometric algebra in ipython notebook

Short version

Can I get nice latex-style printing of sympy's geometric algebra objects in the ipython notebooks?

Longer version

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.

[EDIT EDIT: Updated version of hackiness below]

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.

EDIT: Hacky partial solution

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

Answers (4)

Mike
Mike

Reputation: 20196

EDIT:

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.

Older:

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

user2761381
user2761381

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

user1530392
user1530392

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

user2761381
user2761381

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

[email protected]

Upvotes: 3

Related Questions