marimo icon indicating copy to clipboard operation
marimo copied to clipboard

Add SymPy equation rendering support such that the ouput is on parity with Jupyter's rendering when using SymPy.

Open kamyuen opened this issue 1 year ago • 2 comments

Description

There is currently no way to render equations properly when using SymPy. In Jupyter notebook one usually just calls init_printing() at the beginning of a notebook to allow all subsequent output to be rendered in mathematical notation. Importing SymPy in and calling init_printing() has absolutely no effect and equations are simple output as text. To see the issue just follow the SymPy documentation for setting up this feature https://docs.sympy.org/latest/tutorials/intro-tutorial/printing.html

Suggested solution

Since SymPy has multiple fallbacks on how to render the output, it may be a case of initially capturing the resulting MathJax and rendering using Marimo's md function, just a guess.

Alternative

No response

Additional context

No response

kamyuen avatar May 19 '24 18:05 kamyuen

In the meantime, you can do this:

from sympy import latex
import marimo as mo

def print_sympy(obj):
    return mo.md(f"""
    \[
    {latex(obj)}
    \]
    """)

Playground: https://marimo.app/l/n2kkic

mscolnick avatar May 19 '24 19:05 mscolnick

Adding on to the solution by @mscolnick, you can try adding the _mime_ method to the classes you want to render.

...
from sympy import Symbol as SymbolSympy
from sympy import Integral as IntegralSympy

class Symbol(SymbolSympy):
    def _mime_(self) -> tuple[str, str]:
         return ("text/html", print_sympy(self).text)

class Integral(IntegralSympy):
    def _mime_(self) -> tuple[str, str]:
        return ("text/html", print_sympy(self).text)
...
x, y, z = symbols('x y z', cls=Symbol)
...

Playground: https://marimo.app/l/t1huwf

Updating to add that if you would rather like to use monkey-patching for adding the rendering method, you could change print_sympy, or create a new e.g. sympy_html, to return the mime type and the content (playground https://marimo.app/l/nhxml3):

def patch_sympy(*objs):
    """adds the _mime_() method to the sympy objects
    e.g.
    Symbol._mime_ = sympy_html
    example:
    patch_sympy(Symbol, Integral)
    """
    for obj in objs:
        # the lambda below is our sympy_html 
        obj._mime_ = lambda obj: ("text/html", mo.md(f"""\[{latex(obj)}\]""").text)
...
from sympy import Symbol, Integral
patch_sympy(Symbol, Integral)
...
x, y, z = symbols('x y z')

agostof avatar Jul 23 '24 22:07 agostof

@agostof - your patch is quite nice

if you or @kamyuen or anyone else wants to make a contribution to the repo - you can add this to marimo/_output/formatters

mscolnick avatar Aug 28 '24 21:08 mscolnick

@mscolnick Thanks!

It turns out that patching sympy.core.basic.Printable works nicely. I am adding a formatter and will submit a PR.

agostof avatar Sep 08 '24 18:09 agostof