Skip to content

Commit

Permalink
DOC: explain _latex_repr_() as method implementation (#416)
Browse files Browse the repository at this point in the history
  • Loading branch information
redeboer authored May 16, 2024
1 parent c190cb0 commit 416aaea
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 14 deletions.
48 changes: 35 additions & 13 deletions docs/usage/sympy.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -102,33 +102,55 @@
"\n",
"\n",
"@unevaluated(real=False)\n",
"class PhspFactorSWave(sp.Expr):\n",
"class BreakupMomentum(sp.Expr):\n",
" s: sp.Symbol\n",
" m1: sp.Symbol\n",
" m2: sp.Symbol\n",
" _latex_repr_ = R\"\\rho^\\text{{CM}}\\left({s}\\right)\"\n",
" _latex_repr_ = R\"q\\left({s}\\right)\" # not an f-string!\n",
"\n",
" def evaluate(self) -> sp.Expr:\n",
" s, m1, m2 = self.args\n",
" q = BreakupMomentum(s, m1, m2)\n",
" cm = (\n",
" (2 * q / sp.sqrt(s))\n",
" * sp.log((m1**2 + m2**2 - s + 2 * sp.sqrt(s) * q) / (2 * m1 * m2))\n",
" - (m1**2 - m2**2) * (1 / s - 1 / (m1 + m2) ** 2) * sp.log(m1 / m2)\n",
" ) / (16 * sp.pi**2)\n",
" return 16 * sp.pi * sp.I * cm\n",
" return sp.sqrt((s - (m1 + m2) ** 2) * (s - (m1 - m2) ** 2) / (s * 4))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sympy.printing.latex import LatexPrinter\n",
"\n",
"\n",
"@unevaluated(real=False)\n",
"class BreakupMomentum(sp.Expr):\n",
"class PhspFactorSWave(sp.Expr):\n",
" s: sp.Symbol\n",
" m1: sp.Symbol\n",
" m2: sp.Symbol\n",
" _latex_repr_ = R\"q\\left({s}\\right)\"\n",
"\n",
" def evaluate(self) -> sp.Expr:\n",
" s, m1, m2 = self.args\n",
" return sp.sqrt((s - (m1 + m2) ** 2) * (s - (m1 - m2) ** 2) / (s * 4))"
" q = BreakupMomentum(s, m1, m2)\n",
" cm = (\n",
" (2 * q / sp.sqrt(s))\n",
" * sp.log((m1**2 + m2**2 - s + 2 * sp.sqrt(s) * q) / (2 * m1 * m2))\n",
" - (m1**2 - m2**2) * (1 / s - 1 / (m1 + m2) ** 2) * sp.log(m1 / m2)\n",
" ) / (16 * sp.pi**2)\n",
" return 16 * sp.pi * sp.I * cm\n",
"\n",
" def _latex_repr_(self, printer: LatexPrinter, *args) -> str:\n",
" s = printer._print(self.s)\n",
" s, *_ = map(printer._print, self.args) # or via args\n",
" return Rf\"\\rho^\\text{{CM}}\\left({s}\\right)\" # f-string here!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":::{note}\n",
"For illustrative purposes, the phase space factor defines `_latex_repr_()` [as a printer method](https://docs.sympy.org/latest/modules/printing.html#example-of-custom-printing-method). It is recommended to do so only if rendering the expression class as $\\LaTeX$ requires more logics. The disadvantage of defining `_latex_repr_()` as a method is that it requires more boilerplate code, such as explicitly converting the symbolic {attr}`~sympy.core.basic.Basic.args` of the expression class first. In this phase space factor, defining `_latex_repr_` as a {class}`str` would have been just fine.\n",
":::"
]
},
{
Expand Down Expand Up @@ -537,7 +559,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.8"
}
},
"nbformat": 4,
Expand Down
20 changes: 19 additions & 1 deletion src/ampform/sympy/_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def unevaluated(
>>> @unevaluated
... class Function(sp.Expr):
... x: sp.Symbol
... _latex_repr_ = R"f\left({x}\right)"
... _latex_repr_ = R"f\left({x}\right)" # not an f-string!
...
... def evaluate(self) -> sp.Expr:
... return sp.sqrt(self.x)
Expand All @@ -154,6 +154,24 @@ def unevaluated(
>>> expr.doit()
y
Or, `as a method <https://docs.sympy.org/latest/modules/printing.html#example-of-custom-printing-method>`_:
>>> from sympy.printing.latex import LatexPrinter
>>> @unevaluated
... class Function(sp.Expr):
... x: sp.Symbol
...
... def evaluate(self) -> sp.Expr:
... return self.x**2
...
... def _latex_repr_(self, printer: LatexPrinter, *args) -> str:
... x = printer._print(self.x) # important to convert to string first
... x, *_ = map(printer._print, self.args) # also possible via its args
... return Rf"g\left({x}\right)" # this is an f-string
>>> expr = Function(y)
>>> sp.latex(expr)
'g\\left(y\\right)'
Attributes to the class are fed to the `~object.__new__` constructor of the
:class:`~sympy.core.expr.Expr` class and are therefore also called "arguments". Just
like in the :class:`~sympy.core.expr.Expr` class, these arguments are automatically
Expand Down

0 comments on commit 416aaea

Please sign in to comment.